for循环里的变量闭包

2020-07-01 17:26:48 浏览数 (1)

2016-12-12 14:25:09

很多情况我们在for循环里会给一个数组元素定义事件,例如下面代码

代码语言:javascript复制
for (var i = 0; i < 10; i  ) {
setTimeout(function() { console.log(i); }, 100 * i);
}

介绍一下,setTimeout会在若干毫秒的延时后执行一个函数(等待其它代码执行完毕)。

好吧,看一下结果:

代码语言:javascript复制
10
10
10
10
10
10
10
10
10
10

很多JavaScript程序员对这种行为已经很熟悉了,但如果你很不解,你并不是一个人。 大多数人期望输出结果是这样:

代码语言:javascript复制
0
1
2
3
4
5
6
7
8
9

但是为什么会这样呢?让我们花点时间考虑在这个上下文里的情况。 setTimeout在若干毫秒后执行一个函数,并且是在for循环结束后。 for循环结束后,i的值为10。 所以当函数被调用的时候,它会打印出 10

一个通常的解决方法是使用立即执行的函数表达式(IIFE)来捕获每次迭代时i的值:

代码语言:javascript复制
for (var i = 0; i < 10; i  ) {
    // capture the current state of 'i'
    // by invoking a function with its current value
    (function(i) {
        setTimeout(function() { console.log(i); }, 100 * i);
    })(i);
}

这种奇怪的形式我们已经司空见惯了。 参数 i会覆盖for循环里的i,但是因为我们起了同样的名字,所以我们不用怎么改for循环体里的代码。

0 人点赞