了解JavaScript闭包 - 冻结传递给回调的变量

时间:2014-01-26 12:26:13

标签: javascript closures

我还没有对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 变量已经被“冻结”了调用时的值。

为什么使用包装器函数让传递的值被冻结?

这对我来说并不完全清楚。

3 个答案:

答案 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()外部函数而产生的特定环境是私有的。