JS函数的执行时机

311 阅读1分钟

废话不说上代码

for(var i = 0; i < 6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
//执行输出6个6

输出结果跟我们正常来想的不一样是为什么,为什么不是依次输出0-5呢?
这是因为setTimeout()指定的代码,必须等到本次执行的所有代码都执行完,才会执行。也就是说for循环执行完才轮到它

延迟为 0 意味着“马上”执行,或者尽快执行。事实上实际延迟比设定值更久,在浏览器中,setTimeout() 的每调用一次定时器的最小间隔是4ms

而变量ivar命令声明的,在全局范围内都有效,所以全局只有一个变量i,每一次循环,变量i的值都会发生改变,循环结束执行setTimeout(),此时i的值为6,所以就会打印出6个6

有什么方法可以让代码按正常逻辑运行呢?

方法一:for和let配合使用

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

let声明的变量只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

方法二:使用setTimeout的第三个参数

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

附加参数,一旦定时器到期,它们就会作为参数传递给function

方法三:使用闭包

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