2013-04-07 66 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); 

基本上做同樣的事情在你的第二個代碼示例存根功能。