为什么这会返回3,1?

时间:2015-02-12 14:16:43

标签: javascript

我理解后者,我们在foo对象上调用警报,该对象有另一个名为baz的对象作为其属性,而该对象又有一个名为bar的方法返回值x。由于lexical scope(我认为:)),JS编译器/解释器上升,在x中找到baz并返回1.

我的猜测是,当分配给变量go然后从全局范围调用时,你得到3?只是想知道背景中发生了什么。任何帮助将不胜感激!!!

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

5 个答案:

答案 0 :(得分:7)

当你做这样的事情时:

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

在调用go之前,您会发现foo.baz已失去对bar()的引用。它只是一个指向bar函数的指针,并且与它所附加的对象没有任何关联。这意味着this方法执行后foo.baz将不会是bar

这明确是为.bind()开发的内容。您可以像这样使用它:

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

而且,它会对你有用。你也可以做同样的手动版本:

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

但现在语言中已加入.bind()以帮助您解决此类问题。

答案 1 :(得分:3)

首先,将函数表达式声明为名为go的变量。如果执行函数go this引用全局对象,那么变量x的值为3,这就是alert(go())警告3的原因。另一方面,您执行方法foo.baz.bar()。此处this引用对象(foo),x引用值1。因此它会提醒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

答案 2 :(得分:2)

go-function在窗口中运行,foo.baz.bar-function在对象内运行。 这样做是为了让它返回内部x:

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

编辑: 一个好的经验法则:函数在它们声明的范围内运行。


在.toString()

中可以看到同样的事情
Number(123).toString()

给出了与

不同的结果
Number(456).toString()

即使调用相同的函数。

该函数实际上位于Number.prototype对象中。

答案 3 :(得分:0)

由于您正在将函数提取到变量中,您实际上将函数转移到全局范围,是的。

例如,如果您的对象栏也有函数foo(),并且您获取foo.baz.bar并且bar将包含return this.foo();这会错。 foo()不再存在,因为您只将该函数而不是它原来属于的对象赋给变量。如同,它不是参考。

答案 4 :(得分:0)

在这种情况下,它仅与执行上下文有关。函数总是相同的,唯一改变的是函数中'this'对象的含义。

您可以使用.apply()指定上下文,也可以使用.bind()强制永久强制特定上下文

您可以在我的代码版本中看到它:

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