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
大多数人期望输出结果是这样:
0
1
2
3
4
5
6
7
8
9
setTimeout
在若干毫秒后执行一个函数,并且是在for
循环结束后。 for
循环结束后,i
的值为10
。 所以当函数被调用的时候,它会打印出 10
!
一个通常的解决方法是使用立即执行的函数表达式(IIFE)来捕获每次迭代时i
的值:
for (var i = 0; i < 10; i++) {
(function(i) {
setTimeout(function() { console.log(i); }, 100 * i);
})(i);
}
但是最便捷的方法就是把var改成let就行,当let
声明出现在循环体里时拥有完全不同的行为。 不仅是在循环里引入了一个新的变量环境,而是针对 每次迭代都会创建这样一个新作用域。 这就是我们在使用立即执行的函数表达式时做的事。而const不行,因为变量被const声明之后值就不能改变了,而for循环中的 i 值不断在改变
for (let i = 0; i < 10; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}