Featured image of post JavaScript函数的执行时机

JavaScript函数的执行时机

问题

有这么一段代码,打印的结果和预期不符

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

预期的结果是打印出 0,1,2,3,4,5 ,但是执行的结果是 6,6,6,6,6,6

分析

上面这段代码,用到了 setTimeoutsetTimeout 的作用是设置一个定时器,定时器到期后执行一个函数或指定的一段代码。

上面的代码可以理解为:初始化 i 是 0,然后设置一个打印 i 的定时器,然后让 i 加 1,再次循环设置第二个定时器,直到 i 等于 6 则不再设置定时器,最后在退出 for 循环后,开始执行之前定的 6 个定时器。

由于定时器执行是在for循环结束之后,所以当for 循环结束后,i 的值是 6, 这时候执行 6个定时器,定时器的内容是打印 i,于是打印结果就是 6,6,6,6,6,6

如何打印出符合预期的结果

let i = 0 写在for 循环里面即可

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

其他方法

使用闭包,每次循环从外部把当时 i 的值传给 setClock,由 setClock 用当时的 i 的值设置定时器,最终输出 0,1,2,3,4,5

1
2
3
4
5
6
7
8
9
let i = 0
for(i = 0; i<6; i++){
    function setClock(a){
        setTimeout(()=>{
            console.log(a)
        },0)
    }
    setClock(i)
}

资料来源:饥人谷、MDN