美文网首页
let 和 const

let 和 const

作者: falcon_li | 来源:发表于2018-01-05 15:01 被阅读0次

    一、let

    1.1 let 申明的变量,只能在 let 所在的代码块内有效;

    例:

    { let a = 10; var b = 1; }

    a // ReferenceError: a is not defined.

    b // 1

        b 是 var 声明的变量,所以是全局的,在代码块外也能有效;

    1.2 let 在 for 循环中很适用;

    for (let i = 0; i < 10; i++) {

    // ...

    }

    console.log(i); // ReferenceError: i is not defined

    二、var 和 let 在 for 循环中声明变量的区别

    var a = [];

    for (var i = 0; i < 10; i++)

    {

    a[i] = function ()

                        {

                            console.log(i);

                        };

    }

    a[6](); // 10

    上面代码中,变量 i 是 var 命令声明的,在全局范围内都有效,所以全局只有一个变量 i 。每一次循环,变量 i 的值都会发生改变,而循环内被赋给数组a的函数内部的 console.log(i) ,里面的  i 指向的就是全局的 i 。也就是说,所有数组 a 的成员里面的 i ,指向的都是同一个 i ,导致运行时输出的是最后一轮的 i 的值,也就是 10。

    var a = [];

    for (let i = 0; i < 10; i++) {

        a[i] = function () { console.log(i);};

    }

    a[6](); // 6

    上面的代码中,i 是 let 声明的,只能在每次循环中有效,每次循环 i 都是一个新的变量; 

    2.1 for 循环的特别之处

    设置循环的部分是一个父作用域,而循环体内部是一个单独的子作用域;

    for (let i = 0; i < 3; i++) {

        let i = 'abc'; console.log(i);

    }

    // abc

    // abc

    // abc

    三次都是输出 abc ,let 变量在不同的作用域中是独立的;

    三、不存在变量提升

    3.1  

    var  变量在声明之前使用,值为 undefined;

    let  变量在声明之前使用,直接报错;

    // var 的情况

    console.log(foo);// 输出undefined

    var foo = 2;

    // let 的情况

    console.log(bar); // 报错ReferenceError

    let bar = 2;

    四、暂时性死区(TDZ)

    4.1 let 变量绑定在块级区域内,不受外部变量的影响;

    var tmp = 123;

    if (true) {

        tmp = 'abc'; // ReferenceError

        let tmp;

    }

    以上代码虽然已在代码块外面声明了变量 tmp,但是在代码块内部,使用 let 重新声明了变量 tmp,所有在声明之前使用 tmp 就直接报错,这里就被成为暂时性死区;

    if (true) {

        // TDZ开始

        tmp = 'abc'; // ReferenceError

        console.log(tmp); // ReferenceError

        let tmp; // TDZ结束

        console.log(tmp); // undefined

        tmp = 123;

        console.log(tmp); // 123

    }

    在上面代码块中,在声明 tmp之前,都属于 tmp 的 TDZ;

    4.2 typeof 不再百分百安全

    typeof x; // ReferenceError

    let x;

    在使用 let 声明 变量 x 之前,x 属于 TDZ 中

    typeof x // "undefined"

    在不使用 let 声明 x 时,不会报错;

    4.3 比较隐蔽的 TDZ

    function bar(x = y, y = 2) {

        return [x, y];

    }

    bar(); // 报错

    在声明 y 之前, x 的默认值 等于 y ,此时 y 处于 TDZ。所以报错;

    // 不报错

    var x = x;

    // 报错

    let x = x; // ReferenceError: x is not defined

    在 x 变量完成声明前使用 x ,x 仍处于 TDZ 中;

    五、不允许重复声明变量

    let 不允许在同一个代码块中,重复声明同一个变量

    // 报错

    function func() {

        let a = 10;

        var a = 1;

    }

    // 报错

    function func() {

        let a = 10;

        let a = 1;

    }

    以上两种情况都会报错;

    在函数内部也不能重复声明变量;

    function func(arg) {

        let arg; // 报错

    }

    function func(arg) {

        {

            let arg; // 不报错

        }

    }

    六、块级作用域

    6.1 需要块级作用域的原因

    场景一:

    var tmp = new Date();

    function f() { console.log(tmp);

    if (false) { var tmp = 'hello world'; } }

    f(); // undefined

    上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

    场景二:

    var s = 'hello';

    for (var i = 0; i < s.length; i++) { console.log(s[i]); }

    console.log(i); // 5

    i 变量本来只是作用在循环中,最后却泄漏成全局变量;

    6.2 块级作用域的使用

    function f1() { let n = 5;

        if (true) { let n = 10;}

        console.log(n); // 5

    }

    以上 变量 n 在代码块内声明,并不会影响代码块外的使用;

    6.3 块级作用域与函数声明;

    避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句

    // 函数声明语句

    {

        let a = 'secret';

        function f() { return a; }

    }

    // 函数表达式

    {

        let a = 'secret';

        let f = function () { return a; };

    }

    另外,还有一个需要注意的地方。ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

    七、do表达式

    在块级作用域前加上 do ,可以得到块级作用域中的值

    let x = do {

                    let t = f(); t * t + 1;

                    };

    八、const

    1.const 声明的是一个只读常量;不能改变,类似 java 中的 带 final 的变量;

    2.const 声明的变量必须赋值,否则会报错

    3.作用域 与 let 相同,只能在块级作用域中

    4.同样有暂时性死区(TDZ)

    5.在同一块级作用域中不能重复声明;

    6.Object.freeze 冻结对象

    九、声明变量的方法

    es5中只能使用 var 和 function 命令;

    es6 中新加了 let 、const、import、class四种方法;

    十、顶层对象的属性;

    与全局变量是等价的;

    ES6 为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

    相关文章

      网友评论

          本文标题:let 和 const

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