JS 函数的执行时机

75 阅读2分钟
let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

打印出来的是6个6为什么会出现这样的情况?

  1. 我们要先清楚setTimeout这个函数,setTimeout的作用是当你把当前最近的事情做完之后再来执行setTime里面的事情。
  2. 当前最近的事情是for循环内的内容,所以代码的执行顺序是先将for循环执行完,i变成了6,此时在执行setTimeout里面的console.log(i)
for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

这个代码能打印出来0~5 js为了符合正常人的思维而做的改变,本质上和上面的代码是相同的。但是在这里,let和for一起使用时,会加东西。在每一次for循环时把i复制了一遍,留在setTime里面,这样执行setTime时会打印出之前的i。

下面的代码也能实现打印0~5

for(var i=0; i<6; ++i) {   //利用闭包
    !(function(j) {
        setTimeout(function(){
            console.log(j)
        }, 0)
    })(i)
}

setTime详解
setTimeout是一个异步任务,JavaScript是一个单线程的语言,而异步明显和单线程不能共存。 那浏览器为了实现异步,就采用了事件循环机制和任务队列,任务队列里面保存了JavaScript未来需要执行的任务。

事件循环是指浏览器会不停的从任务队列中取任务去执行,只有在当前任务执行完后才会继续从任务队列中取任务并执行

而setTimeout并不是精确的在未来某个时间执行回调函数,而是在一段时间后将代码放到任务队列末尾。如果时间设置为0,则表示立即插入,而不是立即执行。必须等待任务队列中排在前面的任务执行完之后才会执行该任务。因此,有时候setTimeout并不是那么准确的调用函数