天天看点

对循环中setTimeout执行过程的思考

参考文章:这个前端面试在搞事!

题目

for (var i = ; i < ; i++) {
  setTimeout(function() {
    console.log(i);
  },  * i);
  }
           

答案

每隔一秒输出5

分析

由于setTimeout会延迟执行,所以处理结果是执行循环之后再将里面的函数压入事件队列。执行循环的时候压入队列的函数是:0s console.log(i);1s console.log(I);….所以每隔一秒输出i。而由于i是var类型的,由于变量提升,最后的i都变成5了。于是最后都打印5

如果将上面的代码变成这样:

for (let i = ; i < ; i++) {
  setTimeout(function() {
    console.log(i);
  },  * i);
  }
           

显然是每隔一秒输出0,1,2,3,4了,因为let存在块级作用域。

那么将代码变成这样呢?

for (var i = ; i < ; i++) {
  setTimeout((function(i) {
    console.log(i);
  })(i), i * );
}
           

由于setTimeout里面是立即执行函数,于是便不会根据时间延迟将函数压入队列,而是直接进入事件循环执行。所以会直接进行输出0,1,2,3,4。