采取以下两个例子。在两个示例中,变量i
被指定为0到9.在第一个示例中,在调用超时函数时,i
已经被赋值为9.我不知道设置超时时i
的值。
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
第二个例子给了我期望的值{{1}} - 那么就垃圾收集而言,这是如何工作的呢? GC会在什么时候删除此值?在回调函数结束时?或者会有某种内存泄漏?
答案 0 :(得分:4)
在第一个示例中,callback
是函数function(){alert('...' + i);}
,其中i
是定义callback
的范围内的变量,即i
in for(var i = 0; ...)
。
即使在setTimeout(callback, 2000)
为i
时调用了0
,在2000毫秒之后(这是足够的时间来运行整个for
循环,i
将成为callback
10,当调用The first test returns: 10
时,将显示callback
。
但是,在进行闭包的第二个示例中,function(){alert('...' + i);}
本身仍为i
,但由于匿名函数中的参数i
会影响其父作用域,{{1} } callback
中的参数是匿名函数中的参数i
,而不是i
中的for(var i = 0; ...)
。
由于JavaScript使用按值调用,i
由callback
设置(function(i){...}(i))
时i
将被“修复”,这会生成带参数i
的匿名函数然后立即按值for(var i ...)
(在{{1}})中应用它。
GC在这里没有任何作用。 (GC的不同行为 - 除了内存使用和时间 - 意味着GC中存在错误。)