2009-12-30 71 views
2

嗨我有以下JavaScript代碼,我試圖運行。我的目標是在不同的範圍和不同類型的JavaScript調用中掌握this的含義。與JavaScript中的「this」對象混淆匿名函數

如果你看下面的代碼:我有一個內部匿名函數,它被分配到innerStuff變量。在這樣的匿名函數中,this指向window對象,而不是外部函數對象或其他任何東西。儘管它仍然可以訪問out函數的變量。

無論如何,我不確定,爲什麼會這樣;但如果你看下面的代碼,我通過this的形式thatinnerStuff以後,它工作得很好,並在控制檯打印對象doofus屬性。

var someStuff = { 
     doofus:"whatever", 
     newF: function() 
     { 
      var that = this; 
      console.log(that); 
      var innerStuff = function(topThis){ 
       console.log(topThis); 
      }; 

      return innerStuff(that); 
     } 
    } 

    someStuff.newF(); 

現在我只是稍微改變一個代碼。而不是將其分配給innerStuff,我就直接調用它返回的功能,如下圖所示:

var someStuff = { 
     doofus:"whatever", 
     newF: function() 
     { 
      var that = this; 
      console.log(that); 
      return function(that){ 
       console.log(that); 
      }(); 
     } 
    } 

    someStuff.newF(); 

此打印未定義內部匿名函數。是否因爲參數that和外部函數中定義的that之間有衝突? 我以爲參數會覆蓋可見性。爲什麼價值不被保留?

這是非常令人困惑的。

另一方面,如果我沒有通過that,而只是使用它,因爲知名度是存在的,結果是正確的和預期的。

我錯過了什麼?這是變量之間的衝突,存在於相同的範圍內嗎? 有沒有很好的理由,那內部函數有this綁定到window對象?

回答

9

this JavaScript中引用您稱爲方法的對象。如果您調用的函數爲someObject.functionName(args),則this將被綁定到該對象。如果您只是調用裸函數,如functionName(args),則this將被綁定到window對象。

在第二個示例中newF的內部,您在內部函數中映射that變量,但未傳遞任何內容,因此未定義。

 var that = this; 
     console.log(that); 
     return function(that){ 
      console.log(that); 
     }(); 

你可能想下面相反,如果你想要的東西,就相當於你的第一個例子(順便that到內部功能):

 var that = this; 
     console.log(that); 
     return function(that){ 
      console.log(that); 
     }(that); 

或下面的,如果你不」不想影子,並只使用外部函數的結合:

 var that = this; 
     console.log(that); 
     return function(){ 
      console.log(that); 
     }(); 
+0

啊!!我不能相信我錯過了這一點。萬分感謝。 – Priyank 2009-12-30 18:09:18

+0

那麼,它*與完全不同於在其他語言中綁定方法是如何工作的... – bobince 2009-12-30 18:28:46

1

在你的第二個例子,當你調用匿名函數,參數沒有定義(你沒有向它傳遞任何東西。)你可以這樣做:

newF: function() 
    { 
     var that = this; 
     console.log(that); 
     return function(that){ 
      console.log(that); 
     }(that); // note that we are passing our 'that' in as 'that' 
    } 

這將保持變量的正確值。

但是,因爲你是上述範圍界定var that,你可以只取出功能參數,以及:

newF: function() 
    { 
     var that = this; 
     console.log(that); 
     return function(){ 
      console.log(that); 
     }(); // 'that' is referenced above. 
    } 

至於爲什麼匿名函數有window爲他們this:每當你調用一個函數不利用上下文(即somef() vs context.somef()this將指向window對象。

您可以使用.apply(context, argumentsArray) or .call(context, arg1, arg2, arg3)覆蓋該函數並在函數上傳遞this。舉個例子:

newF: function() 
    { 
     console.log('Outer:', this); 
     var innerF = function(){ 
      console.log('Inner:', this); 
     }; 
     return innerF.apply(this,arguments); 
    } 
1

在你的第一個代碼示例,匿名功能,雖然功能是someStuff對象的成員中聲明,是不是someStuff對象的成員。爲此,該函數中的this是對窗口對象的引用。如果你想調用匿名函數,並有超過this引用控制,你可以做到以下幾點:

var someStuff = { 
    doofus:"whatever", 
    newF: function() 
    { 
     var that = this; 
     console.log(that); 
     var innerStuff = function(){ 
      console.log(this); 
     }; 

     return innerStuff.apply(this); 
    } 
} 

someStuff.newF(); 

在你的第二個例子,你實際上是創建一個匿名函數,執行它,然後返回值匿名函數返回。但是,您的匿名函數沒有返回任何內容。此外,你有一個變量名稱衝突。你可以這樣做:

var someStuff = { 
    doofus:"whatever", 
    newF: function() 
    { 
     var that = this; 
     console.log(that); 
     return function(){ 
      console.log(that); 
      return true; 
     }(); 
    } 
} 

someStuff.newF(); 

我添加了回真正的,因爲你的函數應該返回的東西,因爲這是執行它返回的匿名函數的返回值的功能。無論是返回true還是false,還是字符串或對象或其他任何依賴於場景的內容。

+0

我同意第一點,我可以使用「應用」調用,但第二點是不正確的。沒有名稱衝突,因爲傳遞的參數會覆蓋外部函數中的參數。 我做的錯誤是我在撥打電話時沒有將param傳遞給匿名函數。 [正如Brian在上面的例子中所示]他的建議解決方案工作得很好,他的立場得到了糾正。 至於回報價值;我不認爲我太在乎;我只是想看看這個/這個值在內部函數中的範圍。 儘管感謝您的幫助。 – Priyank 2009-12-30 18:24:46