js_let与var在for循环中的底层实现模拟

for循环的执行顺序

  • for循环的代码如下

    •     var a = []
          for (var i = 0; i < 3; i++) {
              a[i] = function () {
                  console.log(i)
              }
          }
        
          a[0]() // 3
          a[1]() // 3
          a[2]() // 3
      
    • 其调用顺序为:

      • 定义循环变量var i = 0
      • 判断循环i<3
      • 判断结果为true则执行循环体代码
      • 循环变量自增i++

当使用var声明变量时的for循环的底层实现

  • 上面的代码相当于

    •     var a = []
        
          var i = 0
          if (i < 3) {
              a[i] = function () {
                  console.log(i)
              }
          }
          i++ // 1
        
          if (i < 3) {
              a[i] = function () {
                  console.log(i)
              }
          }
          i++ // 2
        
          if (i < 3) {
              a[i] = function () {
                  console.log(i)
              }
          }
        
          i++ // 3
        
          // false 不执行退出循环
          if (i < 3) {}
        
          a[0]() // 3
          a[1]() // 3
          a[2]() // 3
      

当使用let声明变量时的for循环底层实现

  • let声明变量时的for循环代码
        var a = []
        for (let i = 0; i < 3; i++) {
            a[i] = function () {
                console.log(i)
            }
        }

        a[0]() // 0
        a[1]() // 1
        a[2]() // 2
  • 使用let声明变量时的底层实现模拟
        var a = []

        let i = 0
        if (i < 3) {
            // 模拟底层实现
            let k = i // js引擎通过赋值操作
            a[k] = function () {
                console.log(k)
            }
        }

        i++

        if (i < 3) {
            let k = i
            a[k] = function () {
                console.log(k)
            }
        }

        i++

        if (i < 3) {
            let k = i
            a[k] = function () {
                console.log(k)
            }
        }
        i++

        // 判断为false 跳出循环 
        if (i < 3) {}
        a[0]() // 0
        a[1]() // 1
        a[2]() // 2
  • 使用引用值作为let声明变量的赋值
        var a = []
        for (let i = {
                num: 0
            }; i.num < 3; i.num++) {
            a[i.num] = function () {
                console.log(i.num)
            }
        }
        a[0]() // 3
        a[1]() // 3
        a[2]() // 3
  • 使用引用值作为let声明变量的赋值的底层实现模拟
        var a = []
        let i = {
            num: 0
        }
        if (i.num < 3) {
            // 块作用域中只会复制父作用域中let所声明的循环变量
            let k = i
            a[k.num] = function () {
                console.log(k.num)
            }
        }
        i.num++
        if (i.num < 3) {
            let k = i
            a[k.num] = function () {
                console.log(k.num)
            }
        }
        i.num++

        if (i.num < 3) {
            let k = i
            a[k.num] = function () {
                console.log(k.num)
            }
        }
        i.num++
        // 判断为false, 跳出循环

        a[0]() // 3
        a[1]() // 3
        a[2]() // 3

参考博客

[for循环中let与var的区别,块级作用域如何产生与迭代中变量i如何记忆上一步的猜想]https://www.cnblogs.com/echolun/p/10584703.html

posted @ 2021-09-23 11:27  Syinho  阅读(137)  评论(0)    收藏  举报