JS 函数的执行时机

95 阅读2分钟

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

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

setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式;其意思就是尽快,而不是马上

通俗的解释

因为 setTimeout 就像一个定时闹钟,一定时间就会执行,当i=0循环到6时,setTimeout才执行 ,就打印里面的内容。 6个6

其他同学的的解释

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

如何理解异步呢? 异步代码不等待结果,直接进行下面的代码,所以定时器只是开启了,而没有立即执行里面的代码,等到当前运行坏境的代码执行完之后再回来执行定时器里面的代码。总结:异步就是不等待结果的代码。

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

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

通俗的解释

这个for循环在大众来看,就是打出0,1,2,3,4,5的。JS为了满足大众的需求,就创造出一个打印0,1,2,3,4,5的

其他同学的的解释

因为在for语句里用let声明变量是局部变量遵循块作用域,所以每次for循环执行时都会生成一个单独的作用域,也会生成一个新的i,相当于有6个i。 此时,每次执行setTimeout()时都会打印出对应的i,打印结果就是0、1、2、3、4、5了。

打印出 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)
    })
}