7月19号

29 阅读1分钟

下面执行后输出什么?为什么?

for(var i = 1; i <= 5; i ++){
  setTimeout(function timer(){
          console.log(i)
  }, 0)
}

输出5个6:

JS是单线程按顺序执行的。 每一次for循环都执行一次setTimeout,因为setTimeout是异步函数,每一次执行都不执行里面的函数,而是被放在队列中等待主任务for循环全部执行完毕(此时i是6)才执行timer,。 因为var定义的是函数作用域,所以最后引用的i都是一个值6。for循环执行了5次,所以输出5次都是6。

若是想要输出12345: 1使用let替换var。 2利用setTimeout第三个参数作为timer函数的参数传入。 3立即执行函数+闭包,使传入的i被作为timer函数作用域的形参


因为setTimeout为宏任务,由于JS中单线程eventLoop机制,在主线程同步任务执行完后才去执行宏任务,因此循环结束后setTimeout中的回调才依次执行,但输出i的时候当前作用域没有,往上一级再找,发现了i,此时循环已经结束,i变成了6。因此会全部输出6。