美文网首页
块级绑定

块级绑定

作者: JasonQiao | 来源:发表于2017-04-19 23:00 被阅读28次

    因为ES6之前存在变量提升问题,容易造成问题,ES6引入了块级作用域。

    块级声明

    块级作用域在函数或者块({})中创建。

    let声明,不提升,不可重复声明。

    例子1(报错):

    var count = 30;
    // throws an error
    let count = 40;
    

    例子2(不报错,在块中创建一个局部变量count,屏蔽了全局count直到从块中出来):

    var count = 30;
    if (condition) {
        // doesn't throw an error
        let count = 40;
        // more code
    }
    

    const声明,不提升,不可重复声明。声明的同时必须初始化,不可更改。

    但是const声明的对象属性值是可以修改的,只是绑定不能修改。
    例子:

    const person = {
        name: "Nicholas"
    };
    // works
    person.name = "Greg";
    // throws an error
    person = {
        name: "Greg"
    };
    

    暂存死区(Temporal Dead Zone,TDZ)

    let和const声明的变量只能在声明之后调用。在声明之前引用会报引用错误,即使是用typeof之类的安全操作也不行。
    例子:

    if (condition) {
        console.log(typeof value);  // throws an error
        let value = "blue";
    }
    

    当JS引擎看到一个即将执行的代码块时,对var声明的变量做声明提升,而对let和var声明的变量则将声明放到一个暂存死区,任何在之前尝试读取TDZ中变量的操作都会导致运行时错误。直到执行流到let和var的定义,相应变量才从TDZ移除。
    但是下面的例子不会报错,因为引用变量时它不在TDZ,即使没有也只是返回undefined。
    例子:

    console.log(typeof value);     // "undefined"
    if (condition) {
        let value = "blue";
    }
    

    TDZ只是区块绑定的一个特别方面。另外一个在于循环当中。

    循环中的区块绑定

    在for循环中使用let声明的变量,在每次循环事都绑定了不同的变量。例子:

    var funcs = [];
    for (let i = 0; i < 10; i++) {
        funcs.push(function() {
            console.log(i);
        });
    }
    funcs.forEach(function(func) {
        func();     // outputs 0, then 1, then 2, up to 9
    })
    

    如果是var声明的i,那输出结果就会是10个10,只能使用IIFE来解决。对于for in和for of同样适用。例子:

    var funcs = [],
        object = {
            a: true,
            b: true,
            c: true
        };
    for (let key in object) {
        funcs.push(function() {
            console.log(key);
        });
    }
    funcs.forEach(function(func) {
        func();     // outputs "a", then "b", then "c"
    });
    

    如果是var key in object的话输出回事3个c。
    let在for循环中的这个特性是ES6特别制定的,和变量提升无关。
    对于const,在for循环中会报错,因为声明的变量不可修改,但在for in和for of中表现和let一致。例子:

    var funcs = [];
    // throws an error after one iteration
    for (const i = 0; i < 10; i++) {
        funcs.push(function() {
            console.log(i);
        });
    }
    

    全局区块绑定

    使用let和const声明的全局变量不会绑定到window的属性,但使用var声明的全局变量会绑定到window的属性。
    例子:

    // in a browser
    let RegExp = "Hello!";
    console.log(RegExp);                    // "Hello!"
    console.log(window.RegExp === RegExp);  // false
    const ncz = "Hi!";
    console.log(ncz);                       // "Hi!"
    console.log("ncz" in window);           // false
    

    最佳实例

    声明变量尽量使用const,除非你确定需要修改才使用let。

    相关文章

      网友评论

          本文标题:块级绑定

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