最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does this return 3, 1? - Stack Overflow

programmeradmin5浏览0评论

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));
发布评论

评论列表(0)

  1. 暂无评论