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 。這在代碼中能確保基本層次的不可變性,有助於防止某些類型的錯誤。

相關文章
相關標籤/搜索