为什么用 let 声明循环变量可以避免一直打印最后一位

  在let出现之前,for循环定义的迭代变量会渗透到循环体外部:

    for(var i = 0;i<5;i++){
        // 执行逻辑
    }
    console.log(i); //5

  改成使用let之后,这个问题就消失了,因为迭代变量的额作用域仅限于for循环内部:

    for(let i= 0;i<5;i++){
        // 执行逻辑
    }
    console.log(i);  //i is not defined

  在使用var的时候,最常见的问题就是对迭代变量的奇特声明和修改:

    for(var i = 0;i<5;i++){
        setTimeout(() => {
            console.log(i); //  5 5 5 5 5
        }, 0);
    }
    //你可能以为它会打印0 1 2 3 4
    //实际上会输出 5 5 5 5 5

  为了能够更加直观的看出执行的过程,将代码改造成一下过程:

    for(var i = 0;i<5;i++){
        console.time("计时器一");
        setTimeout(() => {
            console.time("计时器二");
            console.log(i);
            console.timeEnd("计时器二");
        }, 0);
        console.timeEnd("计时器一");
    }

在这里插入图片描述

  可以直观的看到,计时器一执行完了才去执行计时器二,在执行计时器二的时候,i已经是5了。
  之所以会这样是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的i都是同一个变量,因为输出的都是同一个最终值。
  而在使用let声明迭代变量时,JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。而每个setTimeout引用的都是不同的变量实例,所以输出的时我们期望的值,也就是循环过程中每个迭代变量的值:

    for(let i = 0;i<5;i++){
        setTimeout(() => {
            console.log(i); //0 1 2 3 4 
        }, 0);
    }
    for(let i = 0;i<5;i++){
        console.time("计时器一");
        setTimeout(() => {
            console.time("计时器二");
            console.log(i);
            console.timeEnd("计时器二");
        }, 0);
        console.timeEnd("计时器一");
    } 

在这里插入图片描述

  这种每次迭代声明一个独立变量实例的行为适用于所有风格的for循环,包括for infor of

小建议:
  尽量少或者不使用var去声明,使用let有助于提升代码质量,因为变量有了明确的作用域、声明位置。

文章大多表述文字源于:红宝书第四版28-29页,少部分表述为个人,表达不到位请原谅

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值