JS_探究for循环和let变量

452 阅读2分钟

for循环创建几个作用域

for (let i = 0; i< 3; i++) {
  let a = i
  setTimeout(() => {
    debugger
    let b = a
    let c = i
  }, 1);
}

断点 查看scope,运行结果

结论:可以看到for循环创建了两个作用域

  • 一个是for循环本身创建的父级作用域,记录循环变量i的值
  • 一个是for循环内部创建的子作用域,记录变量a的值

for循环的循环变量使用let声明到底是怎么做到变量隔离的

先引用一段阮一峰 ES6入门的内容

tips:

  • 每一次循环都是一个新的块级作用域
  • 每一次循环的i都是重新声明的
  • javascript引擎会记住上一轮循环的值,初始化本轮的循环变量i

模拟代码

var a = [];
var _i; // 模拟js引擎,记录上一轮循环的值
{
    let i = 0;
    _i = 0;
    if(i < 3){ // 创建for循环内部的子作用域
        a[i] = function() {
            console.log(i)
        }
    }
}
{  // 第二次循环,创建新的块级作用域
    let i = ++_i;
    if(i < 3){ // 创建for循环内部的子作用域
        a[i] = function() {
            console.log(i)
        }
    }
}
{
    let i = ++_i;
    if(i < 3){ // 创建for循环内部的子作用域
        a[i] = function() {
            console.log(i)
        }
    }
}
a[1](); // 1

再来模拟一次文章一开始的代码,看下作用域是否一致

var a = [];
var _i; // 模拟js引擎,记录上一轮循环的值
{
  let i = 0;
  _i = 0;
  if (i < 3) { // 创建for循环内部的子作用域
    let a = i
    setTimeout(() => {
      let b = a
      let c = i
      console.log(i)
    }, 1);
  }
} { // 第二次循环,创建新的块级作用域
  let i = ++_i;
  if (i < 3) { // 创建for循环内部的子作用域
    let a = i
    setTimeout(() => {
      let b = a
      let c = i
      console.log(i)
    }, 1);
  }
} {
  let i = ++_i;
  if (i < 3) { // 创建for循环内部的子作用域
    let a = i
    setTimeout(() => {
      debugger
      let b = a
      let c = i
      console.log(i)
    }, 1);
  }
}
// 输出结果:0 1 2

运行结果:

结论:跟我们一开始的scope一致

  • for循环创建了两个作用域,自身的循环变量的块级作用域,以及内部循环体的块级作用域
  • 使用let声明的循环变量,每次循环都会创建新的块级作用域,以及声明新的循环变量

Happy Ending... 💃💃💃💃💃💃