我和我的一个朋友目前正在讨论什么是 JS 中的闭包,什么不是。我们只是想确保我们真正正确地理解它。
让我们举这个例子。我们有一个计数循环,并希望在控制台上延迟打印计数器变量。因此,我们使用setTimeout和 闭包 来捕获计数器变量的值,以确保它不会打印 N 次值 N。
setTimeout
没有闭包 或任何接近 闭 包的错误解决方案是:
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); }
这当然会打印i循环后值的 10 倍,即 10。
i
所以他的尝试是:
for(var i = 0; i < 10; i++) { (function(){ var i2 = i; setTimeout(function(){ console.log(i2); }, 1000) })(); }
按预期打印 0 到 9。
我告诉他他没有使用 闭包 来捕获i,但他坚持认为他是。我通过将 for 循环体放入另一个循环体(将他的匿名函数传递给)来证明他不使用 闭包 ,再次打印 10 次 10 次。如果我将他的函数存储在 a 中并在循环 之后 执行它,同样适用,也打印 10 乘以 10。所以我的论点是 他并没有真正 捕获 的值 ,使他的版本 不是 闭包。setTimeout``setTimeout``var __i
setTimeout``setTimeout``var
我的尝试是:
for(var i = 0; i < 10; i++) { setTimeout((function(i2){ return function() { console.log(i2); } })(i), 1000); }
所以我捕获(在闭包中i命名),但现在我 返回 另一个函数并传递它。 就我而言,传递给 setTimeout 的函数确实捕获了 .i2 __ i
i2
现在谁在使用闭包,谁不使用?
请注意,这两种解决方案都延迟在控制台上打印 0 到 9,因此它们解决了原始问题,但我们想了解这两种解决方案中的哪一个 使用闭包 来完成此任务。
编者注:JavaScript 中的 所有函数都是闭包,如本文所述。然而,我们只对确定这些函数的子集感兴趣,这些函数从理论的角度来看是有趣的。 此后,除非另有说明,否则对闭包 一词的任何引用都将指代此功能子集。
闭包的简单解释:
现在让我们用它来确定谁使用闭包,谁不使用(为了解释起见,我命名了函数):
案例一:你朋友的节目
for (var i = 0; i < 10; i++) { (function f() { var i2 = i; setTimeout(function g() { console.log(i2); }, 1000); })(); }
在上面的程序中有两个函数:f和g。让我们看看它们是否是闭包:
f
g
对于f:
console
因此该函数f不是闭包。
对于g:
因此, 当* 从内部 引用g该函数时,该函数是自由变量i2(它是 的上值)g的闭包。 ***setTimeout
对你不利: 你的朋友正在使用闭包。内部函数是一个闭包。
案例 2:您的程序
for (var i = 0; i < 10; i++) { setTimeout((function f(i2) { return function g() { console.log(i2); }; })(i), 1000); }
对你有好处: 你正在使用闭包。内部函数是一个闭包。
所以你和你的朋友都在使用闭包。别吵了。我希望我清除了闭包的概念以及如何为你们俩识别它们。
编辑: 关于为什么所有函数都关闭的简单解释(学分@Peter):
首先让我们考虑以下程序(它是控件):
lexicalScope(); function lexicalScope() { var message = "This is the control. You should be able to see this message being alerted."; regularFunction(); function regularFunction() { alert(eval("message")); } }
lexicalScope
regularFunction
message
接下来让我们考虑以下程序(它是替代方案):
var closureFunction = lexicalScope(); closureFunction(); function lexicalScope() { var message = "This is the alternative. If you see this message being alerted then in means that every function in JavaScript is a closure."; return function closureFunction() { alert(eval("message")); }; }
closureFunction
我们从中推断出什么?