JS函数的执行时机

209 阅读1分钟

一个函数的调用时机不同,得到的结果就不同。

先来看这样一段代码:

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

以上代码为什么会打印出六个6而不是0,1,2,3,4,5,呢?

因为setTimeout是异步执行,每一次for循环的时候,setTimeout都执行一次,但是console.log(i)没有被执行,而是被放到了任务队列里,等待执行。

只有主线上的任务执行完,才会执行任务队列里的任务。也就是说它会等到for循环全部运行完毕后,才会执行console.log(i),但是当for循环结束后此时i的值已经变成了6,因此虽然定时器执行了6次,控制台上的内容依然是6。

让上面代码打印 0、1、2、3、4、5 的方法:

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

在for和let一起使用的时候,运行环境中 i 的值是每一个循环时创建的 i,所以得到了0-5的值。

除了使用 for let 配合,可以打印出 0、1、2、3、4、5的其他方法:

  • 立即执行函数

用立即执行函数给每一个 i 创造一个独立作用域,在立即执行函数执行的时候,i 的值被赋值给ii

for (var i=0; i<6; i++) {
    (function(ii) {
        setTimeout( ()=> {
            console.log(ii);
        }, 0 );
    })(i);
}
  • 拆分结构

还可以将setTimeout的定义和调用分别放到不同部分:

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