JS函数的执行时机

272 阅读2分钟

在不同的情况下,js的函数会有不同结果

例:


let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
//6 6 6 6 6 6

111.PNG

这段代码的结果是6个6,而不是我们潜意识认为的0~5,这是为什么呢?

这是因为上面代码中含有setTimeout函数,这个函数的意思简单理解为就是过一会执行里面的代码,可以自己设定过多长时间来执行,单位为毫秒

原因

因为setTimeout是异步执行的,就是过一会儿再执行。所以在上面for循环中每次循环setTimeout都会执行一次,但是里面的函数没有执行。它会被放进任务队列,而for循环完后,setTimeout会执行里面的函数,从而打印出6个6

其它方法打印出0~5

1. 在for循环中使用let

for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
// 0 1 2 3 4 5

222.PNG

这是将i绑定到for循环中,而每一次循环中的i都是新的i,每次循环JS都会记住这个值,然后复制,下次循环在这个值的基础上进行重新计算。这样for循环结束后,steTimeout打印i的值便是0~5

2. 使用闭包

for (var i=0; i<6; i++) {
    (function(j) {
        setTimeout(()=> {
            console.log( j );
        }, j*1000 );
    })(i);
}
//0 1 2 3 4 5

333.PNG

因为实际参数与定时器i有强依赖,通过闭包,让i的变量留在内存中,输出j时,引用外部i的变量,而i值在每次循环中都确定了。所以会输出0~5

3. 使用steTimeout的第三个参数

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

444.PNG

每次传入的参数都是for循环中i的值,所以会输出0~5

注意

方法2和方法3是网上寻找的,某些具体原理并不知晓,可能以后理解后再单独阐述