举例

在 JavaScript 里函数的执行时机不同会产生不同的结果,举例如下

  • 例 1:常规顺序

    1. let a = 1;
    2. function fn(){
    3. console.log(a)
    4. }
    5. fn() //1
  • 例 2:赋值前调用函数 ```javascript let a = 1 function fn(){ console.log(a) } fn(); //1 a = 2

let a = 1; function fn(){ console.log(a) } a = 2; fn() //2

  1. - 3:调用后使用 setTimeout 延迟执行
  2. ```javascript
  3. let a = 1
  4. function fn(){
  5. setTimeout(()=>{
  6. console.log(a)
  7. },0)
  8. }
  9. fn();
  10. a = 2 //2

结论

函数在执行时才会调用

问题

  • 所以当 for 循环和 setTimeout 一起使用时,会不能正常打印出结果

    1. let i = 0
    2. for(i = 0; i<6; i++){
    3. setTimeout(()=>{
    4. console.log(i)
    5. },0)
    6. }
    7. // 6,6,6,6,6,6
    • for 循环后产生 6 个 setTimeout 函数,每次循环 i 自增 1,当函数开始执行时访问的都是最终的变量 i ,此时 i == 6,所以打印出 6 个 6。

      解决办法

  • 想让上面代码打印 0、1、2、3、4、5 可以使用下面的方法

    1. for(let i = 0; i<6; i++){
    2. setTimeout(()=>{
    3. console.log(i)
    4. },0)
    5. }
    6. // 0,1,2,3,4,5
    • 将 let 写到 for 循环里面,这样每次 for 循环都会隐式的将变量 i 复制一个到函数中储存起来,这样函数每次执行时访问的是内部的变量 i ,可以输出正确的结果。
  • 除了使用 for let 配合,还可以使用立即执行函数解决这个问题

    1. for(let i = 0; i<6; i++){
    2. ! function(a){
    3. setTimeout(()=>{
    4. console.log(a)
    5. },0)
    6. }(i)
    7. } // 使用立即执行函数,将变量 i 作为参数传进去