《JS 函数的执行时机》

112 阅读1分钟

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

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

原因:

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

setTimeout是指过一段时间之后再打印,而i是先进行声明的,let在for循环外面,i从0开始随着循环一直增加到6不满足i<6结束循环,则i就停留在6,然后再进行打印, setTimeout(()=>{ console.log(i) },0) 总共循环了6次,所以打印了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

①闭包

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

②利用 setTimeout 的第三个参数,将 i 传进去

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

③利用 const 关键字

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