我还没有对JavaScript闭包有基本的了解;
我对特定情况有疑问,这也许是基本和常见的例子:
在3秒内从1到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 中的函数并访问 i 变量时,其值已经达到4。
案例 B 有效。
当包装器(i)被调用时,它返回
function() { log(i); };
和上面的返回值(函数)是setTimeout里面的内容。 setTimeout里面的内容与Case A
完全相同但是这一次, i 变量已经被“冻结”了调用时的值。
为什么使用包装器函数让传递的值被冻结?
这对我来说并不完全清楚。
答案 0 :(得分:1)
包装函数有自己的i
,它本地作用于它。
在调用i
时,会收到其他wrapper
的值。
如果你把它重写为:
,可能会更清楚function wrapper(notI) {
return function() { log(notI); };
}
答案 1 :(得分:1)
i
中使用的变量wrapper
是已传递的变量(作为副本)作为wrapper
的形式参数。它与i
循环中的for
不一样 - 您可以将该变量重命名为您喜欢的任何内容,代码仍可以使用。
它被冻结,因为它具有每次wrapper
最初调用时的值。
答案 2 :(得分:1)
Closure是一个通过调用外部函数
创建的变量作用域和嵌套函数的环境每次调用wrapper()
时,都会为下面的函数创建每个不同的环境
function wrapper(i) {
return function() { log(i); };
}
以下i
的值与调用wrapper()
时的值相同。每次i
的值对于通过调用wrapper()
外部函数而产生的特定环境是私有的。