2014-01-26 64 views
1

我還沒有對JavaScript閉包的基本理解;瞭解JavaScript閉包 - 將凍結變量傳遞給回調

我有一個關於具體的情況,或許也基本和常見的例子一個問題:

從1數到3在3秒內

見的jsfiddle這裏:http://jsfiddle.net/nAh8x/

代碼:

var i, 
    t; 

t = 0; 

// Case A 

for(i=1; i<=3; i++) { 
    setTimeout(function() { log(i); }, t); 
    t += 1000; 
} 

// Case B 

for(i=1; i<=3; i++) { 
    setTimeout(wrapper(i), t); 
    t += 1000; 
} 

function wrapper(i) { 
    return function() { log(i); }; 
} 

// Log utility function 

function log(msg) { 
    $('#log').append(msg + '<br />'); 
} 

案例A不起作用。

很清楚,我爲什麼:每裏面功能的setTimeout時間被稱爲和訪問變量,它的價值已經達到了4

案例作品。

包裝(I)被稱爲返回

function() { log(i); }; 

和上面的返回值(函數)是裏面的setTimeout發生的事情。善有善報,裏面的setTimeout是完全一樣的情況一個

但是這一次,我變量已經「凍結」與通話的時間值。

爲什麼使用包裝函數讓傳遞的值被凍結?

這並不完全清楚。

+0

Paulo,我不希望不友善,但你的開頭聲明需要修改。它應該是:「我*還沒有*對JavaScript關閉有一個基本的理解」。你所掙扎的是基本概念,即閉包捕獲它的局部變量,並繼續允許內部函數訪問這些變量和自由變量,即使在外部函數完成並返回之後。爲了發生這種情況,必須存在對內部函數的持久引用,例如通過賦值返回的函數。 –

+0

我同意你 – Paolo

+0

Paulo,好吧,也許我稍微不友好,但你把它放在下巴上 - 對你有好處。 –

回答

1

包裝函數有它自己的i,它本地作用於它。

這將在調用wrapper時收到另一個i

,如果你重寫了它,因爲它可能是更清楚:

function wrapper(notI) { 
    return function() { log(notI); }; 
} 
1

wrapper使用的變量i是一個已經通過(作爲副本)作爲正式參數wrapper。這與for循環內的那個不一樣i - 您可以將該變量重命名爲任何您喜歡的內容,並且代碼仍然可以工作。

它被凍結,因爲它具有每次最初調用wrapper時的值。

1

封閉是通過調用外部函數與變量的作用域和嵌套函數創建一個環境,

每次wrapper()被稱爲會有創建的每個不同的環境下面的功能

function wrapper(i) { 
    return function() { log(i); }; 
} 

這裏i的值將與調用wrapper()時的值相同。每次i的值對於通過調用wrapper()外部函數產生的特定環境來說都是私有的。