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 @   Syinho  阅读(124)  评论(0编辑  收藏  举报
编辑推荐:
· 使用 .NET Core 实现一个自定义日志记录器
· [杂谈]如何选择:Session 还是 JWT?
· 硬盘空间消失之谜:Linux 服务器存储排查与优化全过程
· JavaScript是按顺序执行的吗?聊聊JavaScript中的变量提升
· [杂谈]后台日志该怎么打印
阅读排行:
· 2000 Star,是时候为我的开源项目更新下功能了
· 面试官:DNS解析都整不明白,敢说你懂网络?我:嘤嘤嘤!
· [WPF UI] 为 AvalonDock 制作一套 Fluent UI 主题
· 基于.NET WinForm开发的一款硬件及协议通讯工具
· 内网穿透之http代理服务器
点击右上角即可分享
微信分享提示