目前在重看阮一峯老師的 ECMAScript 6 入門),打算將看到的知識點總結概括。es6
不論在面試的過程當中仍是在對代碼進行 lint 的過程當中總過看到關於 let & const & var 的一些聲明的異同的問題,如今就藉助阮一峯老師的書籍對這些知識進行總結概括。面試
let
命令所聲明的變量必定要在聲明後使用,不然報錯。瀏覽器
官方的說法是在 let 聲明一個變量以前使用它是會發生錯誤。官方沒有說到會發生變量提高(hoisting),可是有這樣的兩種現象,在 let 聲明一個變量以前使用這個變量,會提示Uncaught ReferenceError: Cannot access 'foo' before initialization
(不該在變量初始化以前使用這個變量)。而若是使用一個未聲明的變量,則會提示Uncaught ReferenceError: bar is not defined
ide
console.log(foo);
let foo = 1;
// Uncaught ReferenceError: Cannot access 'foo' before initialization
console.log(bar)
// Uncaught ReferenceError: bar is not defined
複製代碼
Let & const 上述的與 var 聲明不一樣之處帶來的另外一個不一樣就是:暫時性死區,函數
可是說到暫時性死區,就不得不先提一下塊級做用域。ui
在 ES5 中只存在全局做用於和函數做用域(指在函數內聲明的全部變量在函數體內始終是可見的,能夠在整個函數的範圍內使用及複用)。函數做用域會致使一些不合理的地方,這也是面試過程當中會考的一些地方,好比在阮老師的博客中的例子:spa
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
複製代碼
而 ES6 新增的塊級做用域能夠很好的解決這個問題,由於在塊級做用域 ({})
聲明的變量是在塊級做用域的外部取不到的。指針
而函數在塊級做用域內的聲明遵循下列規則(能夠遵照):code
var
,即會提高到全局做用域或函數做用域的頭部。一樣是阮老師的例子:ip
// 瀏覽器的 ES6 環境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
複製代碼
而這些又跟暫時性死區又有什麼關係呢?
上述所說,塊級做用域內聲明的變量在此之做用域以外是沒法取到的。一樣的在內部,
ES6 明確規定,若是區塊中存在
let
和const
命令,這個區塊對這些命令聲明的變量,從一開始就造成了封閉做用域。凡是在聲明以前就使用這些變量,就會報錯。
這樣的狀況就能夠稱之爲暫時性死區(TDZ)。
也就是咱們最開始說的在使用 let 關鍵字聲明變量以前聲明一個變量會報錯:
Uncaught ReferenceError: Cannot access 'aa' before initialization
複製代碼
除了這些方面,const 還有其獨特的不一樣之處:
咱們也知道,const 定義一個常量,常量的值是不能改變的,也意味着聲明常量的同時就要給其賦值。其做用域及其表現和 let 相同,也存在TDZ。
可是雖說到如今 const 都很符合咱們的理解,可是 const 所表明的定義的值不能被改變是指變量聲明的時候指向的內存地址所保存的數據不得改動[1]。對於基礎類型的值,const 聲明的變量的值就是內存地址所保存的數據。而對於引用類型的話,const 聲明的變量的值就是指向值所在的內存地址的一個指針。const 不能修改的也是這個指針,而指針所表明的內存地址的值能夠發生改變。
let const var 三個關鍵字聲明變量的不一樣之處有:
from ECMAScript 6 入門 阮一峯 ↩︎