2013-04-07 76 views
0

This code generates x is not definedJS查询 - 全局的window对象

var myobj1 = 
{ 
    x:9, 
    myfunction:function() 
    { 
     if(this === window) 
      alert("x is not Defined"); 
     else if (this === myobj1) 
      alert(this.x); 
     else 
      alert("Error!"); 
    } 
} 

function test() 
{ 
    setTimeout(myobj1.myfunction, 1000); 
} 

test(); 

Whereas this code generates x=9 as output

var myobj1 = 
{ 
    x:9, 
    myfunction:function() 
    { 
     if(this === window) 
      alert("x is not Defined"); 
     else if (this === myobj1) 
      alert(this.x); 
     else 
      alert("Error!"); 
    } 
} 

function test() 
{ 
    setTimeout(function() 
    { 
     myobj1.myfunction() 
    }, 1000); 
} 

有人能解释我为什么“如果不是在测试方法中使用回调方法则全局窗口对象被称为”和“这种情况下回调方法的意义是什么”?

回答

1

当您通过myobj1.myfunctionsetTimeout()时,它只传递函数引用。与对象的任何连接都将丢失。 setTimeout()没有能力在任何特定对象的上下文中调用它的函数引用。因此,您必须通过传递自己的函数来自己完成该功能,该函数将在该对象的上下文中调用该方法,或者您可以在现代浏览器中使用.bind()来做同样的事情。

当你这样做:

setTimeout(myobj1.myfunction, 1000); 

JavaScript解释器获取函数引用了myobj1.myfunction并传递到setTimeout()。它产生相同的结果,因为这:

var fn = myobj1.myfunction; 
setTimeout(fn, 1000); 

当它被传递给setTimeout(),它仅仅是一个函数引用,而不是在任何对象的上下文中调用等fn()。请记住,对象上的方法是“恰好”恰好是函数的对象的属性。函数内部的指针this取决于它的调用方式。如果它没有使用myobj1.myfunction()中的对象上下文调用,或者使用.apply().call()明确调用,那么this指针将不会是您的对象。

正如你发现的那样,你可以创建自己的一个小存根函数,它将在适当的对象的上下文中调用它。在现代浏览器中,您还可以使用.bind()这样的:

setTimeout(myobj1.myfunction.bind(myobj1), 1000); 

基本上做同样的事情在你的第二个代码示例存根功能。