2013-08-03 70 views
3

請看下面的兩個例子。在這兩個示例中,變量i都被指定爲0到9.在第一個示例中,在調用超時函數時,i已被賦值爲9.我不知道在超時時間爲i的值組。Javascript - 幫助理解變量行爲

for(var i = 0; i < 10; i++) { 
    var callback = function() { 
     alert('The first test returns: ' + i); 
    }; 

    if(i === 0) setTimeout(callback, 2000); 
} 

在第二選項中,我們可以通過它傳遞到一個新的環境繼續存在的i值(請糾正我,如果這個術語是不正確的)。

for(var i = 0; i < 10; i++) { 
    var callback = (function(i) { 
     return function() { 
      alert('The second test returns: ' + i); 
     } 
    })(i); 

    if(i === 0) setTimeout(callback, 2000); 
} 

第二個例子給我我所期望的價值,0 - 所以儘可能的垃圾收集去如何工作的呢? GC在什麼時候刪除該值?在回調函數的末尾?或者會有某種內存泄漏?

+0

這不是這個問題的目的,我只是爲解釋目的創建一個異步機制。 – lwansbrough

+0

我認爲setInterval是更好的方法來處理事情..將你的代碼減少到一半 –

+2

你完全錯過了這一點。 – lwansbrough

回答

4

在第一個例子,是callback功能function(){alert('...' + i);},其中i是在範圍的變量,其中callback被定義,即,在for(var i = 0; ...)i

即使當i0,2000毫秒後setTimeout(callback, 2000)被調用,這是足夠的時間通過整個for循環運行,i將成爲10,並且當callback被調用,The first test returns: 10將被顯示。

然而,在其中一個閉合件是由第二個例子中,callback本身仍然是function(){alert('...' + i);},但是由於參數i在一個匿名函數陰影其父範圍,icallback是參數i在匿名函數,而不是ifor(var i = 0; ...)

由於JavaScript使用呼叫按值,即i將被「固定」時callback(function(i){...}(i)),這使得與參數i匿名函數然後通過值i(在for(var i ...))立即應用它設置。

GC在這裏沒有任何作用。 (GC的不同行爲 - 除內存使用和定時外 - 意味着GC中存在一個錯誤。)

+0

這是完全一樣的,我懷疑。很好的解釋,謝謝。所以我在使用閉包的長時間運行代碼中運行沒有內存問題的風險呢? (假設for循環有合理的界限?) – lwansbrough

+0

我對垃圾收集器的瞭解不多,但我懷疑(不確定)閉包沒有太大的區別,只是可能有一些關於佔用範圍的信息一些記憶。 – JiminP

+1

我必須深入瞭解一下,感謝您的幫助! – lwansbrough