【JS】for循环里使用setTimeout的一些思考


捕获变量怪异之处
快速的猜一下下面的代码会返回什么:

for (var i = 0; i < 10; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}
介绍一下,setTimeout会在若干毫秒的延时后执行一个函数(等待其它代码执行完毕)。

好吧,看一下结果:

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

0
1
2
3
4
5
6
7
8
9
还记得我们上面提到的捕获变量吗?

我们传给setTimeout的每一个函数表达式实际上都引用了相同作用域里的同一个i。

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

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

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);
}

声明:麋鹿与鲸鱼|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 【JS】for循环里使用setTimeout的一些思考


Carpe Diem and Do what I like