关于let关键字的经典面试题分析

写出下列代码的运行结果

1、使用var关键字声明循环变量i

 var arr = [];
        for (var i = 0; i < 2; i++) {
            arr[i] = function() {
                console.log(i);
            }
        }
        arr[0]();
        arr[1]();

运行结果:2 2

2、使用let关键字声明循环变量i

 let arr = [];
        for (let i = 0; i < 2; i++) {
            arr[i] = function() {
                console.log(i);
            }
        }
        arr[0]();
        arr[1]();

运行结果:0 1

【解析】

向arr数组添加值,值为函数,(注意:此时函数并没有执行)。因为循环执行了两次,故在循环结束后数组中会被添加两个值,这两个值都是函数。

当函数被调用时要输出变量i的值,arr[0]()与arr[1]()实际上是在调用数组中的函数,首先通过数组下标的形式取到数组中的值,由于值就是函数,所以在值的后面可以直接添加小括号来调用函数让函数执行,函数执行完成之后输出的变量i的值。首先我们发现在函数内部并未定义变量i的值,故函数执行时在自己 的作用域下是找不到变量i的值的,根据作用域链查找原则,其要向上一层查找变量

1、使用var关键字声明循环变量i

由于使用lvar关键字声明的变量不具有块级作用域,

循环结束后数组中存储了2个函数,在函数执行时,函数内部还是没有自己的变量i,所以还是要向上一级作用域中进行查找。在当前代码中,其上一层就是全局作用域。在全局作用域下是有变量i的,其就是函数循环时所创建的全局变量i由于函数在执行时循环已经结束,故i的值为不满足循环条件时的值(i=2)

 当前代码的关键点在于变量i是全局的,函数执行时输出的都是全局作用域下的i值,故输出结果为2 2;

 

 

 

 

2、使用let关键字声明循环变量i

由于使用let关键字声明的变量具有块级作用域,循环执行了用let关键字声明的变量,在循环结束产生了两个块级作用域,产生的两个块级作用域中都有自己 的变量i,i=0和i=1都有自己的块级作用域。

循环结束后数组中仍存储了2个函数,在函数执行时,函数内部还是没有自己的变量i,所以还是要向上一级作用域中进行查找。在当前代码中,函数的上一级作用域实际上循环产生的块级作用域,所以数组中的两个函数在执行时,要分别在自己对应的块级作用域中查找i的值,故数组第一个函数在执行时输出的是第一个块级作用域中变量id的值即为0,数组第二个函数在执行时输出的是第二个块级作用域中变量i的值即为1

当前代码的关键点在于每次循环都会产生一个块级作用域,每个块级作用域变量i的值都是不同的,函数执行时输出的是自己上一级作用域下变量i的值,也就是循环产生的块级作用域下i的值,故输出结果为0 1;

 

posted @ 2021-07-01 16:41  蛋蛋仔  阅读(232)  评论(0编辑  收藏  举报