让我们来看这样一段代码,
let i = 0
for(i = 0; i < 6; i++){
setTimeout(()=>{
console.log(i)
},0) // 定时器
}
问:输出什么?
答案不是0,1,2,3,4,5,而是6个6。
看上去是不是很反人类?
原因主要是setTimeout()作为一个定时器,它并不是立即执行的,而是在进程队列中等待当前任务完成后执行,本例中当前任务就是for循环,所以在for循环完成之后,i已经从0变成了6,此时才会触发之前在队列中排着队的6个定时器,每个定时器输出当前i的值,即6个6。
如何"正常人"一点呢?
很简单,在for循环的初始就用let变量声明i即可
for(let i = 0; i < 6; i++){
setTimeout(()=>{
console.log(i)
},0) // 定时器
}
// 输出0,1,2,3,4,5,看上去正常多了
究其原因,是ES6在let和for同时使用的时候,做了特殊的处理,把每次i的值临时存了起来,这样在for循环结束时触发定时器,就可以取到这些临时值,使结果看起来符合逻辑。
还有其他方法吗?
自执行函数
for (var i = 0; i < 6; i++) {
(function (i) {
setTimeout(() => console.log(i), 1000*i)
})(i)
}