258 关键字let

Posted jianjie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了258 关键字let相关的知识,希望对你有一定的参考价值。

let(★★★)

ES6中新增了用于声明变量的关键字let:

  • let关键字就是用来声明变量的
  • 使用let关键字声明的变量具有块级作用域
  • 在一个大括号中,使用let关键字声明的变量才具有块级作用域, var关键字是不具备这个特点的
  • 防止循环变量变成全局变量
  • 使用let关键字声明的变量没有变量提升
  • 使用let关键字声明的变量具有暂时性死区特性
  • 【我的补充】使用let关键字声明的变量,不能被重复声明

1、let声明的变量只在所处于的块级有效

 if (true) { 
     let a = 10;
 }
console.log(a) // a is not defined

注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。

    if (0) {
        let a = 11;
        let b = 22;
        console.log(a);
    } else {
        console.log(b);  // b is not defined
    }

2、不存在变量提升

console.log(a); // a is not defined 
let a = 20;

3、暂时性死区

利用let声明的变量会绑定在这个块级作用域,不会受外界的影响

 var tmp = 123;
 if (true) { 
     tmp = 'abc';
     let tmp; 
 } 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>使用let关键字声明变量</title>
</head>

<body>
    <script type="text/javascript">
        // let关键字就是用来声明变量的

        // 使用let关键字声明的变量具有块级作用域

        // 在一个大括号中 使用let关键字声明的变量才具有块级作用域, var关键字是不具备这个特点的

        // 防止循环变量变成全局变量

        // 使用let关键字声明的变量没有变量提升

        // 使用let关键字声明的变量具有暂时性死区特性


        /* --------let关键字就是用来声明变量的-------- */
        let a = 10;
        console.log(a);

        /* --------使用let关键字声明的变量具有块级作用域-------- */
        if (true) {
            let b = 20;
            console.log(b)

            if (true) {
                let c = 30;
            }
            console.log(c); // c is not defined
        }
        console.log(b) // b is not defined

        /* -------在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的--------- */

        if (true) {
            let num = 100;
            var abc = 200;
        }
        console.log(abc); // 200
        console.log(num) // num is not defined


        /* -------防止循环变量变成全局变量--------- */
        // 【(1)如果用var声明,则for循环结束后,i的值是2,i在全局可用; (2)此时,i 和 for循环进行绑定,在for循环外面是访问不到的。】
        for (let i = 0; i < 2; i++) {}
        console.log(i);


        /*-----使用let关键字声明的变量没有变量提升------*/
        console.log(a); // Cannot access 'a' before initialization
        let a = 100;


        /* -------使用let关键字声明的变量具有暂时性死区特性------- */
        // 【块级作用域里的变量跟外面的同名变量没关系】
        var num1 = 10;
        if (true) {
            let num1 = 20;
            console.log(num1); // 20
        }
        console.log(num1); // 10

        // 下面的报错,就是暂时性死区
        var num2 = 66;
        if (true) {
            console.log(num2); // Cannot access 'num2' before initialization
            let num2 = 66;
        }
        console.log(num2); // 

        /* 【我补充的】-------使用let关键字声明的变量,不能被重复声明------- */
        var aa = 10
        if (true) {
            let aa = 20;
            console.log(aa);
            let aa = 30; // Identifier 'num' has already been declared
            console.log(aa);

        }
        console.log(aa);
    </script>
</body>

</html>

我的补充
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="lodash.js"></script>
</head>

<body>
    <button>11</button>
    <button>22</button>
    <button>33</button>
    <button>44</button>
    <button>55</button>
</body>

</html>
<script>
    let btns = document.querySelectorAll('button');
    for (var i = 0; i < btns.length; i++) {
        console.log(i); // 0 1 2 3 4 
        btns[i].addEventListener('click', function() {
            // (1)当前元素的索引; (2)不是循环结束后的i;(3)改成var,则每次点击都输出5。
            console.log(i);
        })
    }
    // console.log(i); // (1)报错;(2)改成var,则输出5。
</script>

4、经典面试题

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

技术图片

经典面试题图解:此题的关键点在于变量i是全局的,函数执行时输出的都是全局作用域下的i值。


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

技术图片

经典面试题图解:此题的关键点在于每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的,函数执行时输出的是自己上一级(循环产生的块级作用域)作用域下的i值.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>经典面试题</title>
</head>

<body>
    <script type="text/javascript">
        let arr = [];

        // 【(1)每轮循环,都创建一个函数,循环2轮,创建了2个函数arr[0]、arr[1],这2个函数没调用,不执行。(2)如果用var,则循环结束后,i的值为2,所以调用arr[0]()、arr[1]()的时候,i的值就是2,输出的结果都是2;(3)函数执行时,函数里没有局部变量i,所以就往上一级作用域查找i,此时for循环中,用var声明的i就是全局的。】
        // 【用let声明:(1)循环结束后,产生了2个块级作用域,每个作用域都有自己的i,i处于不同的块级作用域,互不影响】
        for (let i = 0; i < 2; i++) {
            // 【(1)函数名是arr[i];(2)函数并没有传参,所以arr[i]的i并不是函数的参数,两者没有任何关系。(2)函数执行时,函数里没有局部变量i,所以就往上一级作用域查找i,此时for循环中,用let声明的i就是块级作用域的,每个函数就到自己的块级作用域中查找i。】
            arr[i] = function() {
                console.log(i);
            }
        }

        arr[0](); // 0
        arr[1](); // 1

        console.log('------------------------------');

        let arr1 = [];

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

        arr1[0](i); // 2
        arr1[1](i); // 2
    </script>
</body>

</html>

以上是关于258 关键字let的主要内容,如果未能解决你的问题,请参考以下文章

jacript var let const 区别

如何用“let”和“const”替换此代码中的“var”关键字?

等效于链式 LINQ 扩展方法调用中的 'let' 关键字的代码

等效于链式 LINQ 扩展方法调用中的 'let' 关键字的代码

无法保留嵌套片段

js中let和const关键字