JS 函数的执行时机

180 阅读1分钟

让我们来看这样一段代码,

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