admin管理员组

文章数量:1026989

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 piler/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());

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 piler/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());

Share Improve this question edited Feb 12, 2015 at 15:39 Antonio Pavicevac-Ortiz asked Feb 12, 2015 at 14:16 Antonio Pavicevac-OrtizAntonio Pavicevac-Ortiz 7,75920 gold badges75 silver badges156 bronze badges 2
  • 1 All because of execution context... first alert of 3 because this refers to global context and thus this.x returns 3..and 1 is pretty much obvious.. – Rakesh_Kumar Commented Feb 12, 2015 at 14:21
  • go() will return undefined... it is not a function but a variable! – kasper Taeymans Commented Feb 12, 2015 at 14:22
Add a ment  | 

5 Answers 5

Reset to default 7

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.

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

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.

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.

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));

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 piler/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());

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 piler/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());

Share Improve this question edited Feb 12, 2015 at 15:39 Antonio Pavicevac-Ortiz asked Feb 12, 2015 at 14:16 Antonio Pavicevac-OrtizAntonio Pavicevac-Ortiz 7,75920 gold badges75 silver badges156 bronze badges 2
  • 1 All because of execution context... first alert of 3 because this refers to global context and thus this.x returns 3..and 1 is pretty much obvious.. – Rakesh_Kumar Commented Feb 12, 2015 at 14:21
  • go() will return undefined... it is not a function but a variable! – kasper Taeymans Commented Feb 12, 2015 at 14:22
Add a ment  | 

5 Answers 5

Reset to default 7

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.

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

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.

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.

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));

本文标签: javascriptWhy does this return 31Stack Overflow