关于let你不知道的知识点——红宝石书笔记记录

let与var的区别

关于let和var的区别可能大家都知道了,主要有以下几点:

1、var没有块级作用域(但有函数作用域),而let有块级作用域。

2、var存在变量提升,而let没有变量提升。

3、var可以声明重名的变量,let不可以声明重名的变量。

for循环中的let声明

1、解决循环遍历渗透到外部的缺点

看下面两段代码:

        for(var i = 0; i < 5; i++){
            console.log('--------');
        }
        console.log(i);// 5

这段代码输出的i是5,原因是var声明的变量没有块级作用域。

        for(let i = 0; i < 5; i++){
            console.log('--------');
        }
        console.log(i); // ReferenceError: i is not defined

这段代码结果是ReferenceError,原因是let声明的变量有块级作用域。

说这一点的原因是,大家以后在用for循环时,尽量用let来声明循环变量,因为指不定以后写代码时一不小心就在两个循环中都用了var声明同一个变量,这样第二个for循环很可能就会受影响!

2、在每一次循环中let声明的变量都是不同的变量实例

2.1 var

看下面两段代码:

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

大家猜这段代码结果是多少,你是不是以为是 0 1 2 3 4,但其实是5 5 5 5 5。

这是为什么呢?首先搞懂setTimeout。

这其实就是之前说过的JS事件循环,具体请看我的文章:JavaScript-事件循环

以为setTimeout是宏任务,它会等到所有同步任务执行完后再执行。举个例子大家就懂了:

        for(var i = 0; i < 5; i++){
            console.log('---');
            setTimeout(() => console.log(i),0);
        }
        for(var j = 0; j < 5; j++){
            console.log('000000');
        }

这两个for循环,输出结果是这样的:即所有同步代码执行完后再执行异步任务。 

setTimeout(function,0)还有很多妙用,之后也会为大家带来这些小妙招。

说回来,最上面那个var的for循环执行过程就如下:

红宝石书上的解释:“在退出循环时,迭代变量保存的时导致循环退出的值:5。在之后执行超市逻辑时,所有的i都是同一个变量,因而输出的都是同一个最终值

setTimeout的代码是最后执行,然而在执行同步代码时,第一次循环给了第一个setTimeout的i为0,第二次循环给了i值为1,因为大家用的都是同一个1,所以第二次循环修改为1后,第一次循环给的那个异步任务的i值也会变为1(因为此时还没开始执行异步任务,所以修改是有效的)。

2.2 let

把上面那段代码换成let:

        for(let j = 0; j < 5; j++){
            console.log('---');
            setTimeout(() => console.log(j),0);
        }

这次输出就是0 1 2 3 4了:

为什么呢?

红宝石书上原话是:“在使用let声明迭代变量时,JavaScript引擎在后台为每个迭代循环声明一个新的迭代变量,每个setTimeout引用的都是不同的变量实例” 。

其实就是上面那幅图,每次给setTimeout的i值,前面都不会更新了,因为每次给的i值都是一个新的变量实例

注意:这种每次循环中声明一个独立变量的行为适用于所有for循环,包括for-in和for-of。

----------------------------------------------------------------------------------------

今天刚开始写读书笔记,以后会坚持写的,将一些我没经常用到的知识点记录一下。这本书真的很好,可以说让我注意到了许多平时没注意的细节,比如虽然以前知道var没有块级作用域,但我用for循环时还是用的var声明循环变量,以后就记得了,一定要用let,这样代码更严谨一点。

猜你喜欢

转载自blog.csdn.net/huiaixing/article/details/125034871