不僅是塊級做用域,你不知道的let和const

ES6新增了兩個重要的關鍵字letconst,相信你們都不陌生,可是包括我在內,在系統學習ES6以前也只使用到了【不存在變量提高】這個特性。javascript

  • let聲明一個塊級做用域的本地變量
  • const語句聲明一個塊級做用域的本地常量,不能夠從新賦值

支持塊級做用域

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

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

總結

  1. let/const支持函數做用域和塊級做用域,var只有函數做用域
  2. let/const不存在變量提高,var存在變量提高
  3. let/const同一做用域內不能夠重複聲明,var能夠重複聲明
  4. let/const存在暫存死區,var不存在

面試題

let b = 1;

function test4() {
    console.log(b);
    let b = 2;
}
test4()

2019-10-22-102654.png

相關文章
相關標籤/搜索