我和我的一位朋友正在讨论JS中的闭包是什么以及它不是什么。我们只是想确保我们真正理解它。
让我们拿这个例子来说。我们有一个计数循环,希望延迟一段时间后将计数器变量打印在控制台上。因此,我们使用setTimeout
和闭包来捕获计数器变量的值,以确保它不会打印N次值为N的值。
没有闭包或与闭包相似的任何东西的错误解决方案如下:
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
循环结束后,它将打印i
的值10次,即10。
所以他的尝试是:
for(var i = 0; i < 10; i++) {
(function(){
var i2 = i;
setTimeout(function(){
console.log(i2);
}, 1000)
})();
}
按预期打印0到9。
我告诉他,他没有使用闭包来捕获i,但他坚持说他使用了。我通过将for循环体放在另一个setTimeout
中(将他的匿名函数传递给setTimeout
),再次打印10次10来证明他没有使用闭包。如果我将他的函数存储在一个var
中,并在循环之后执行它,也会打印10次10。因此,我的论点是他实际上并没有真正“捕获”i的值,使他的版本不是一个闭包。
我的尝试是:
for(var i = 0; i < 10; i++) {
setTimeout((function(i2){
return function() {
console.log(i2);
}
})(i), 1000);
}
我捕获了i(在闭包中命名为i2),然后现在我返回另一个函数并传递它。 在我的情况下,传递给setTimeout的函数真正捕获了i。
现在谁在使用闭包,谁不是?
请注意,两个解决方案都会延迟地将0到9打印到控制台,因此它们解决了原始问题,但我们想要理解这两个解决方案中哪个使用闭包来完成这一点。