ES6 之 let 與 const
ES2015(ES6) 新增加了兩個重要的 JavaScript 關鍵字:let和const。let 宣告的變數只在 let 命令所在的程式碼塊內有效。const 宣告一個只讀的常量,一旦宣告,常量的值就不能改變。
let 命令
基本用法:
{ let a = 0; var b = 1; } a // ReferenceError: a is not defined b // 1
程式碼塊內有效
let 是在程式碼塊內有效,var 是在全域性範圍內有效:
{ let a = 0; var b = 1; } a // ReferenceError: a is not definedb // 1
不能重複宣告
let 只能宣告一次 var 可以宣告多次:
let a = 1; let a = 2; var b = 3; var b = 4; a // Identifier 'a' has already been declared b // 4
for 迴圈計數器很適合用 let
for (var i = 0; i < 10; i++) { setTimeout(function(){ console.log(i); }) } // 輸出十個 10 for (let j = 0; j < 10; j++) { setTimeout(function(){ console.log(j); }) } // 輸出 0123456789
變數 i 是用 var 宣告的,在全域性範圍內有效,所以全域性中只有一個變數 i, 每次迴圈時,setTimeout 定時器裡面的 i 指的是全域性變數 i ,而迴圈裡的十個 setTimeout 是在迴圈結束後才執行,所以此時的 i 都是 10。
變數 j 是用 let 宣告的,當前的 j 只在本輪迴圈中有效,每次迴圈的 j 其實都是一個新的變數,所以 setTimeout 定時器裡面的 j 其實是不同的變數,即最後輸出 12345。(若每次迴圈的變數 j 都是重新宣告的,如何知道前一個迴圈的值?這是因為 JavaScript 引擎內部會記住前一個迴圈的值)。
不存在變數提升
let 不存在變數提升,var 會變數提升:
console.log(a); //ReferenceError: a is not defined let a = "apple"; console.log(b); //undefined var b = "banana";
變數 b 用 var 宣告存在變數提升,所以當指令碼開始執行的時候,b 已經存在了,但是還沒有賦值,所以會輸出 undefined。
變數 a 用 let 宣告不存在變數提升,在宣告變數 a 之前,a 不存在,所以會報錯。
const 命令
const 宣告一個只讀變數,宣告之後不允許改變。意味著,一旦宣告必須初始化,否則會報錯。
基本用法:
const PI = "3.1415926"; PI // 3.1415926 const MY_AGE; // SyntaxError: Missing initializer in const declaration
暫時性死區:
var PI = "a"; if(true){ console.log(PI); // ReferenceError: PI is not defined const PI = "3.1415926"; }
ES6 明確規定,程式碼塊內如果存在 let 或者 const,程式碼塊會對這些命令宣告的變數從塊的開始就形成一個封閉作用域。程式碼塊內,在宣告變數 PI 之前使用它會報錯。
注意要點
const 如何做到變數在宣告初始化之後不允許改變的?其實 const 其實保證的不是變數的值不變,而是保證變數指向的記憶體地址所儲存的資料不允許改動。此時,你可能已經想到,簡單型別和複合型別儲存值的方式是不同的。是的,對於簡單型別(數值 number、字串 string 、布林值 boolean),值就儲存在變數指向的那個記憶體地址,因此 const 宣告的簡單型別變數等同於常量。而複雜型別(物件 object,陣列 array,函式 function),變數指向的記憶體地址其實是儲存了一個指向實際資料的指標,所以 const 只能保證指標是固定的,至於指標指向的資料結構變不變就無法控制了,所以使用 const 聲明覆雜型別物件時要慎重。