Why does this return 3, 1?

I understand the later, we call the alert on the foo object, which has another object named baz as its property, which in turn has a method named bar that returns the value of x. And because of lexical scope (I think :) ) the JS compiler/interpreter goes up the chain, finds x in baz and returns 1.

My guess is when assigned to the variable go and then called from the global scope, you get 3? Just want to find out what's happening in the background. Any help will be appreciated!!!

var x = 3;

var foo = {
    x: 2,
    baz: {
        x: 1,
        bar: function() {
            return this.x;
        }
    }
}

var go = foo.baz.bar;

alert(go());
alert(foo.baz.bar());

Answers:

Answer

When you do something like this:

var go = foo.baz.bar;
go();

you will find that go has lost the reference to foo.baz before calling bar(). It is just a pointer to the bar function and has no association with the object that it is attached to any more. That means that this will not be foo.baz when the bar method executes.

This is explicitly what .bind() was developed for. You can use it like this:

var go = foo.baz.bar.bind(foo.baz);
go();

And, it will then work for you. You can also do the manual version of the same thing:

var go = function() {return foo.baz.bar();}
go();

but .bind() is built into the language now to help you solve this type of issue.

Answer

In first you declare a function expression to a variable with name go. If you execute function go this refers to the global object and there the variable x has value 3 so that's why it alert(go()) alerts 3. On the other hand you execute the method foo.baz.bar(). Here this refer to the object(foo) and the x has the value 1. So it alerts 1.

var x = 3;

 var foo = {
     x: 2,
     baz: {
       x: 1,
       bar: function() {
         return this.x;
       }
     }
   }
 //here you save a function expression
 //to a variablewith name go
 var go = foo.baz.bar;

 //you execute go but this refer to the global object
 //and x has the value of 3 in the global object
 console.log(go());//this will output 3

 //this refer to the object foo where x has
 //the value of 1
 console.log(foo.baz.bar());//this will output 3

Answer

the go-function runs in the window, the foo.baz.bar-function runs within the object. do this instead to get it to return the inner x:

var go = function(){ return foo.baz.bar(); };

Edit: A good rule of thumb: functions run in the scope they are declared in.


the same thing can be seen in .toString()

Number(123).toString()

gives a different result than

Number(456).toString()

Even though the same function is called.

The function is actually located in the Number.prototype object.

Answer

Since you're fetching a function into a variable you're essentially transferring the function to the global scope, yes.

For example, if your object bar also had a function foo() and you'd fetch foo.baz.bar and bar would contain return this.foo(); it would error. foo() does no longer exist since you assigned just that function, and not the object it belonged to originally, to a variable. As in, it's not by reference.

Answer

In this case it is only about execution context. The function is always the same, the only thing that changes is the meaning of the 'this' object within the function.

You can specify the context by using .apply(), and also you can force permanently a specific context with .bind()

You can see it in my version of your code:

var x = 3;
var foo = {
  x: 2,
  baz: {
    x: 1,
    bar: function() {
      return this.x;
    }
  }
}

var go = foo.baz.bar;   

alert(go.apply(this));    
alert(go.apply(foo));
alert(go.apply(foo.baz));

var goBinded = foo.baz.bar.bind(foo.baz);
alert(goBinded());
alert(goBinded.apply(foo));

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.