ES6新增了兩個重要的關鍵字let
和const
,相信你們都不陌生,可是包括我在內,在系統學習ES6以前也只使用到了【不存在變量提高】這個特性。javascript
var
定義的變量會提高到整個函數做用域內,let/const
則支持塊級做用域。java
塊級做用域: 由
{}
包裹的做用域(函數那種{}不算)
來看一個var
的例子:面試
{ var a = 1; } console.log(a);
此時輸出1,由於var
沒有塊級做用域。函數
來看一個let
的例子(const
效果同樣):學習
{ let a = 1; } console.log(a);
此時會報錯ReferenceError
,由於let/const
支持塊級做用域,因此let
定義的a
只在{}
能夠訪問spa
與var
不一樣的是,let/const
聲明的變量不存在變量提高,也就是說{}
對於let/const
是有效的。code
來看一個var
的例子:ip
console.log(a); var a = 1;
此時會輸出undefined,由於var聲明的變量會提高到做用域頂部(只提高聲明,不提高賦值)作用域
來看一個let
的例子(const
效果也同樣):it
console.log(a); let a = 1;
此時會報錯ReferenceError
,由於let
不存在變量提高
同一做用域內let/const
不能夠重複聲明,var
能夠。
來看一個var
的例子:
var a = 1; var a = 2; console.log(a);
此時會輸出2,var是支持重複聲明的,後面聲明的值會覆蓋前面聲明的值。
來看一個let
的例子(const
效果也同樣):
let a = 1; let a = 2; console.log(a);
此時會報錯SyntaxError
,由於同一做用域內let/const
不能夠重複聲明。
再來看一個不一樣做用域的例子:
let a = 1; { let a = 2; } console.log(a);
此時輸出1,由於二者做用域不一樣
暫存死區TDZ(Temporal Dead Zone)是ES6中對做用域新的語義。
經過let/const
定義的變量直到執行他們的初始化代碼時才被初始化。在初始化以前訪問該變量
會致使ReferenceError
。該變量處於一個自做用域頂部到初始化代碼
之間的「暫存死區」中。
來看如下例子:
function do_something() { console.log(bar); // undefined console.log(foo); // ReferenceError var bar = 1; let foo = 2; } do_something();
var
定義的變量聲明會提高到做用域頂部,因此bar
是undefined,而let
定義的變量從做用域開始到let foo=2
這中間都沒法訪問,訪問會報錯ReferenceError
typeof檢測var定義的變量或者檢測不存在的變量時會返回undefined,若是檢測暫存死區內的變量,會報錯ReferenceError
.
console.log(typeof foo); // undefined console.log(typeof bar); // ReferenceError console.log(typeof bar2); // undefined let bar = 1; var bar2 = 2;
也就是說typeof去檢測未初始化的let
變量時會報錯,var
或者未聲明的變量不會報錯
function test(){ var foo = 33; { let foo = (foo + 55); } } test();
以上函數執行結果是什麼?爲何?
報錯
{}
內有let
定義的foo
,因此存在暫存死區,(foo + 55)
這個表達式是在let foo
以前執行的(賦值時先執行等號右邊的,執行完畢把結果賦給等號左邊),表達式執行的時候尚未初始化foo,因此報錯ReferenceError
let b = 1; function test4() { console.log(b); let b = 2; } test4()