ES6 块级绑定

var 声明与变量提高

使用 var 关键字声明的变量,不管其实际声明位置在何处,都会被视为声明于所在函数的顶部,若是声明不在任意函数内,则视为在全局做用域的顶部。浏览器

function getValue(condition) {
    if (condition) {
        var value = "blue";
        // 其余代码
        return value;
    } else {
        // value 在此处可访问,值为 undefined return null;
    }
    // value 在此处可访问,值为 undefined
}
复制代码

若是你不太熟悉 JS ,或许会认为仅当 condition 的值为 true 时,变量 value 才会被建立。但实际上,value 不管如何都会被建立。 JS 引擎在后台对 getValue 函数进行了调整, 就像这样:安全

function getValue(condition) {
    var value;
    if (condition) { 
        value = "blue";
        // 其余代码
        return value;
    } else {
        return null;
    }
}
复制代码

value 变量的声明被提高到了顶部,而初始化工做则保留在原处。这意味着在 else 分支内 value 变量也是可访问的,此处它的值会是 undefined ,由于它并无被初始化。bash

块级声明

块级声明也就是让所声明的变量在指定块的做用域外没法被访问(在一个函数内部 或 在一个代码块内部)。markdown

let 声明

let 声明的语法与 var 的语法一致。你基本上能够用 let 来代替 var 进行变量声明,但会将变量的做用域限制在当前代码块中(其余细微差异会在稍后讨论)。因为 let 声明并不会被提高到当前代码块的顶部,所以你须要手动将 let 声明放置到顶部,以便让变量在整个代码块内部可用。并发

function getValue(condition) {
    if (condition) {
        let value = "blue";
        // 其余代码
        return value;
    } else {
        // value 在此处不可用
        return null;
    }
    // value 在此处不可用
}
复制代码
禁止重复声明

若是一个标识符已经在代码块内部被定义,那么在此代码块内使用同一个标识符进行 let 声明就会致使抛出错误。函数

var count = 30;
// 语法错误
let count = 40;
复制代码

在嵌套的做用域内使用 let 声明一个同名的新变量,则不会抛出错误。spa

var count = 30;
// 不会抛出错误
if (condition) { 
    let count = 40;
    // 其余代码
}
复制代码
常量声明

ES6 中里也可使用 const 语法进行声明。使用 const 声明的变量会被认为是常量( constant ),意味着它们的值在被设置完成后就不能再被改变。正由于如此,全部的 const 变量都须要在声明时进行初始化。试图对以前用 const 声明的常量进行赋值会抛出错误。code

// 有效的常量
const maxItems = 30;
// 语法错误:未进行初始化
const name;
// 抛出错误
const maxItem = 50;
复制代码

常量声明与 let 声明同样,都是块级声明。这意味着常量在声明它们的语句块外部是没法访问的,声明不会被提高,而且在同一个做用域内不能重复定义。orm

使用 const 声明对象比较特殊,const 声明会阻止对于变量绑定与变量自身值的修改,这意味着 const 声明并不会阻止对变量成员的修改。对象

const person = {
    name: "Nicholas"
};
// 工做正常
person.name = "Greg";
// 抛出错误
person = {
    name: "Greg"
}
复制代码
暂时性死区

当 JS 引擎检视接下来的代码块并发现变量声明时,它会在面对 var 的状况下将声明提高到函数或全局做用域的顶部,而面对 let 或 const 时会将声明放在暂时性死区内。任何在暂时性死区内访问变量的企图都会致使“运行时”错误(runtime error)。只有执行到变量的声明语句时,该变量才会从暂时性死区内被移除并能够安全使用。

循环中的块级绑定
for (var i = 0; i < 10; i++) { 
    process(i);
}
// i 在此处仍然可被访问
复制代码
for (let i = 0; i < 10; i++) {
    process(i);
}
// i 在此处不可访问,抛出错误
console.log(i);
复制代码

由于 var 声明致使了变量提高

循环内的常量声明

在常规的 for 循环中,你能够在初始化时使用 const ,但循环会在你试图改变该变量的值时抛出错误。由于该语句试图更改常量的值。所以,在循环中你只能使用 const 来声明一个不会被更改的变量。

var funcs = [];
// 在一次迭代后抛出错误
for (const i = 0; i < 10; i++) { 
    funcs.push(function() {
        console.log(i);
    });
}
复制代码

const 变量在 for-in 或 for-of 循环中使用时,与 let 变量效果相同。所以下面代码不会致使出错,由于循环为每次迭代建立了一个新的变量绑定,而不是试图去修改已绑定的变量的值。

var funcs = [], object = {
    a: true, b: true, c: true
};

// 不会致使错误
for (const key in object) { 
    funcs.push(function() {
        console.log(key);
    });
}
funcs.forEach(function(func) {
    func();	// 依次输出 "a""b""c"
});
复制代码
全局块级绑定
  • 当在全局做用域上使用 var 时,它会建立一个新的全局变量,并成为全局对象(在浏览器中是 window )的一个属性。这意味着使用 var 可能会无心覆盖一个已有的全局属性。
  • 若你在全局做用域上使用 let 或 const ,虽然在全局做用域上会建立新的绑定,但不会有任何属性被添加到全局对象上。这也就意味着你不能使用 let 或 const 来覆盖一个全局变量,你只能将其屏蔽。
  • 当你不想在全局对象上建立属性时,这种特性会让 let 与 const 在全局做用域中更安全。
  • 想让代码能从全局对象中被访问,你仍然须要使用 var 。在浏览器中跨越帧或窗口去访问代码时,这种作法很是广泛。
块级绑定最佳实践

在默认状况下使用 const ,而只在你知道变量值须要被更改的状况下才使用 let 。这在代码中能确保基本层次的不可变性,有助于防止某些类型的错误。

相关文章
相关标签/搜索