闭包如何影响for循环?

时间:2017-06-13 18:44:13

标签: javascript

我一直在试图理解为什么以下代码片段的行为如下:

    for (var i=1; i<=5; i++) {
        setTimeout( function timer(){
            console.log( i );
        }, i*1000 );
    }  //prints 6 five times with a gap of one second in between each

为什么6?我看到了一些解释,但我仍然无法理解。另外为什么下面的代码有用?

    for (var i=1; i<=5; i++) {
        (function(){
            var j = i;
            setTimeout( function timer(){
                console.log( j );
            }, j*1000 );
        })();
    }

1 个答案:

答案 0 :(得分:0)

你传递setTimeout()相同的lambda五次,每次都引用同一个循环变量i。对于每个调用,在循环退出后评估lambda,当i等于6i++时,检查i <= 5是否为var j;,如果没有,则退出循环)。

lambda引用了变量本身,而不是lambda创建时的值。这在大多数情况下非常有用。不是这个。

var j = i;版本有两个 lambda。具有i的那个会立即执行,其当前值为j。这会创建一个新变量j,该变量位于该lambda的本地。 i初始化为setTimeout()的值,该值是外部lambda执行时的当前值。所以在这种情况下,你给了j你可以考虑的五个不同的lambda,有五个不同的变量,都是j,但有五个不同的值。

内部lambda稍后执行,但它使用i

不同之处在于代码创建了一个唯一的位置来存储for (var i=1; i<=5; i++) { var j = i; setTimeout( function timer(){ console.log( j ); }, j*1000 ); } 的每个

最后一点:在其他一些语言中,这可行:

j

在JavaScript中,它没有。 j的范围不同。在JavaScript中,在这种情况下只会有一个j。这就是使用立即执行的函数的原因:确保有多个@Value