2011-03-25 29 views
2

下面的第一個例子是John Resign的學習高級JavaScript#http://ejohn.org/apps/learn/#62#62。它被稱爲修復破碎的閉合。示例1失敗4次。例2僅僅因爲它有一個包裝函數而不同,它傳遞了4次。這是例如#63來自同一教程來自John Resig#62和#63的JavaScript破碎的閉包和包裝函數

有人可以解釋

1)爲什麼i == count++實例1中失敗。

2)爲什麼i == count++在包裝函數的幫助下傳遞。包裝函數如何改變事物使其工作?

在此先感謝。

實施例1

var count = 0; 
for (var i = 0; i < 4; i++) { 
    setTimeout(function(){ 
    assert(i == count++, "Check the value of i."); 
    }, i * 200); 
} 

實施例2

var count = 0; 
for (var i = 0; i < 4; i++) (function(i){ 
    setTimeout(function(){ 
    assert(i == count++, "Check the value of i."); 
    }, i * 200); 
})(i); 

回答

1
  1. 由於i正在遞增在環路的可能性是強烈,以致每次setTimeout回調調用值i將會是4.
  2. 包裝函數引入了一個新的作用域,允許參數i的值保持其值,即使周圍的i正在循環遞增。

function outerScope() { 
    var x = 2, y = 3; 

    function innerScope() { 
     var x = 3; 

     // Obviously this alerts 3. 
     alert(x); 

     // Since we have no 'y' defined, alert the value 3 from the outer scope. 
     alert(y); 
    } 

    // Introduce a new scope. 
    innerScope(); 

    // Since we have left the inner scope x is now 2. 
    alert(x); 

    // Obviously this alerts 3. 
    alert(y); 
} 
2

這是非常簡單的。 由於setTimeout以「異步」方式執行,因此循環繼續運行,因此無法告知函數執行時i的確切值。

通過使用函數包裝器,實際上你正在將調用的主體作爲一個函數來處理,並且明確地傳遞了i的值。

您可以通過重命名我帕拉姆到j或別的東西的功能,從我清除此和更新功能的內臟給到j

基本上它歸結爲範圍