美文网首页JSweb前端技术分享
67.for循环中的var 和 let

67.for循环中的var 和 let

作者: wo不是黄蓉 | 来源:发表于2022-02-27 22:01 被阅读0次

    day16:
    这段代码我们应该都见过,想要的效果是我们每隔一秒钟分别打印出来1,2,3,4,5。然而,效果却是打印了5,5,5,5,5。但是我们把声明i的声明语句改成let就可以这是为什么呢?

    for (var i = 0; i < 5; i++) {
      setTimeout(() => {
        console.log(i);
      }, i*1000);
    }
    

    原因是因为,var声明的变量会被变量提升,上面一段代码相当于

    var i;
    for (i = 0; i < 5; i++) {
      setTimeout(() => {
        console.log(i);
      }, i*1000);
    }
    

    此时i就是全局对象中的一个属性,即是window下的,因此我们每次修改执行完i的值之后,在异步任务还未执行到的时候for循环已经执行完成了,此时i的值已经被修改成了5,因此每次输出的都是5.
    那么为什么使用let就可以解决呢?
    因为let声明的变量会存在一个块级作用域的概念,使用let声明迭代变量时,js引擎会在后台为每一个迭代循环声明一个新的迭代变量,因此每次使用的i算是不同的。
    如何不使用let来解决var变量作用域相同的问题呢?
    使用闭包
    产生闭包的条件:

    • 内部函数引用外部的变量
    • 有内部函数
    • 有外部函数
      不会用闭包咋办?
      今天看到一句话,觉得刷新了我对闭包的认知。可以将闭包理解成一个创造函数对象的工厂,不会写闭包的按照此套路真是屡试不爽,哈哈哈
      举个例子:
    for (var i = 0; i < 5; i++) {
    //2.a的结果时一个函数
      let a = creater();
    //3.执行i,此时i的值还未改变,此时另一个函数作用域中引用了i变量的值,因此i并不会就此销毁而是会被延用到a函数这个作用域中
      a(i);
    }
    
    //1.creater相当于就是一个工厂函数,用来延长i的作用域
    function creater() {
    //4.此时参数的i就是a中的i。在创建函数时会创建一个作用域链,此时参数中的i指向的是a中的i,而a中的i又是全局中的i,在函数创建过程中会预装载全局变量对象,并保存到内部的scope中。此时就创建了一个新的空间,因此全局变量的修改就不会影响到i的改变。
      return function (i) {
        setTimeout(() => {
          console.log(i);
        }, i*1000);
      };
    }
    

    分析过程看上面代码注释。
    何以见得全局变量的修改就不会影响到i的改变?

    for (var i = 0; i < 5; i++) {
      let a = creater();
      a(i);
    }
    
    console.log(i + " start");
    i = 10;
    function creater() {
      return function (i) {
        setTimeout(() => {
          console.log(i);
        }, i * 1000);
      };
    }
    console.log(i + " end");
    

    打印i时,会发现i的值已经改为了10,发现start之前未5,end时是10.说明此时修改的i就是全局变量中的i。

    还有一种常见的修改思路:使用IIFE。原理相同不多做分析。

    for (var i = 0; i < 5; i++) {
      (function (i) {
        setTimeout(() => {
          console.log(i);
        }, 1000);
      })(i);
      creater(i);
    }
    

    相关文章

      网友评论

        本文标题:67.for循环中的var 和 let

        本文链接:https://www.haomeiwen.com/subject/qsxkrrtx.html