JS 函数的执行时机

205 阅读1分钟

本文将介绍setTimeout()在JavaScript中循环执行时发生的情况。

我们从一段简单的代码出发

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

在for循环结束时,变量i实际上的值是6,而不是5。为什么呢?

让我们来回顾一下for循环中实际发生的情况:

  • 第一遍:i是1,检查i<6?是的,输出i,执行i++
  • 第二遍:i是2,检查i<6?是的,输出i,执行i++
  • 第三遍:i是3,检查i<6?是的,输出i,执行i++
  • 第四遍:i是4,检查i<6?是的,输出i,执行i++
  • 第五遍:i是5,检查i<6?是的,输出i,执行i++
  • 第六遍:i是6,检查i<6?不是,退出循环。

setTimeout

如果我们希望在输出循环中的每个数字之前先暂停一秒钟怎么办?JavaScript为我们提供了setTimeout方法,我们可以使用此方法来实现。

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

但是,当执行此代码后,我们会惊讶地发现,输出结果是6 6 6 6 6 6

哇!为什么没有输出1 2 3 4 5 6?

简短的答案是,在for循环执行完成之前,不会触发setTimeout函数回调。在完成for循环之后,setTimeout将使用最终值回调执行。

两种解决方法

那么有什么解决的方法呢?

  1. 使用let关键字
for(let i = 0;i < 6; i++){
    setTimeout(function(){
        console.log(i);
    }, 1000);
}
  1. 使用IIFE (Immediately Invoked Function Expression)
for(var i = 0; i < 6; i++){
    (function(i){
        setTimeout(function(){
            console.log( i);
        }, 1000);
    })(i);
}