JS 函数的执行时机

2020-04-08  本文已影响0人  我愚蠢的理想主义啊
let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
for执行的结果是输出6,6,6,6,6,6

为什么上面的代码会打印 6 个 6,这是因为setTimeout()是异步执行,即使delay值取的为0,也只是意味着“马上”执行,或者尽快执行。所以它会在for循环结束之后执行,此时变量i的值已经被覆盖为6了,所以会执行6次console.log(6),得到结果就是6,6,6,6,6,6

如何让以上代码打印出0--5

在for循环表达式中使用let声明表达式变量

可以将代码改成以下方式:

for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}
此时for执行的结果是输出0,1,2,3,4,5

因为let有自己的作用域块,所以在for循环表达式中使用let其实就等价于在代码块中使用let,也就是说:

1.for( let i = 0; i< 5; i++) 这句话的圆括号之间,有一个隐藏的作用域。

2.for( let i = 0; i< 5; i++) { 循环体 } 在每次执行循环体之前,JS 引擎会把 i 在循环体的上下文中重新声明及初始化一次。

类似于:

{
  // 父块作用域
  let i = 0;
  // 第一次循环
  {
    // 子块作用域,将i传进来,并进行形参赋值(相当于有形参i的函数自执行)
    let i = 0; // 这里`JavaScript`引擎帮我们传入实参,并进行形参赋值
    setTimeout(() => console.log(i), 0);
  }
  i++;
  // 第二次循环
  {
    let i = 1;
    setTimeout(() => console.log(i), 0);
  }
  // ...
}

此时就会输出0,1,2,3,4,5

还有一种方式可以打印出0--5

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

把i作为参数传入到setTimeout中即可实现打印出0--5了。

上一篇下一篇

猜你喜欢

热点阅读