JS 函数的执行时机

59 阅读2分钟

1. 为什么如下代码会打印 6 个 6

let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
复制代码

函数的调用时机不同,结果也会不同。setTimeout() 在指定的时间后执行一段代码. 它需要如下参数:

  • 要运行的函数,或者函数引用。
  • 表示在执行代码之前等待的时间间隔(以毫秒为单位,所以1000等于1秒)的数字。如果指定值为0(或完全省略该值),函数将立即运行。
  • 更多的参数:在指定函数运行时,希望传递给函数的值.

因为setTimeout是一个异步任务,执行操作时会被浏览器丢到另一个任务队列里去,浏览器这时候会继续执行for循环。每一次for循环的时候,setTimeout都执行一次,但是里面的函数()=>{console.log(i)}没有被执行,而是被放到了任务队列里面,等待执行,for循环了6次,就放了6次,当主线程执行完成后,才进入任务队列里面执行。这时候因为for循环i=6了,所以输出的全部都是6。

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

for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
复制代码

因为let变量的作用域只能在当前函数中,所以每次for循环生成的都是一个新的i, setTimeout里输出的i就是这个新的i,这个i是不会变化的,所以输出的就是正常的。

3. 除了使用 for let 配合,还有什么其他方法可以打印出 0、1、2、3、4、5

1.闭包
let i 
for(i = 0; i<6; i++){
  !function(j){
      setTimeout(()=>{
        console.log(j)
      },0)
  }(i)
}

2.const关键字
let i
for(i = 0; i<6; i++){
    const x = i
    setTimeout(()=>{
      console.log(x)
    })
}

3.利用 setTimeout 的第三个参数,将i传进去
let i
for(i = 0; i<6; i++){
    setTimeout((value)=>{
      console.log(value)
    },0,i)
}

参考文章:juejin.cn/post/685716…