(Day 22) ES6 的 let 、const
前言
在 ES6 新增兩種變數方法 let
、 const
,不過我們比較常把 const
叫做常數,主要是因為 var
的特性 容易觸發 Bug , 這邊與 var
的差異主要有:
- 作用域範圍不同
- 提升特性不同
- 全域不掛在 window 下
在提及這些不同特性之前,先大致介紹一下這兩個用法的差別。
let 、 const 基本介紹
let
能夠重新賦值,但不能重複宣告
1 | let String1 = 'test1' |
const
不能重新賦值,也不能重新宣告。
1 | const String1 = 'test1' |
要補充一點如果 const
的值是物件,對物件底下的屬性賦值, const
則能接受這種操作繼續使用。
1 | const obj = {} |
作用域不同
在過去 var
作用域是根據函式作用域,而 let
、 const
則是以 { ... }
Block 區塊做為作用域,來看看以下範例:
1 | var name1 = 'Ryder' |
結果是 Ryder, Ryder
,這範例很好理解,不論是 var
還是 let
, name = 'Jack'
的作用範圍都只在 test()
這個函式中,console 的位置則是在全域,自然都會是 Ryder
,那麼再來看看這個範例:
1 | var name1 = 'Ryder' |
結果會是 Jack, Ryder
,這是因為上面提到的, let
是以 { ... }
區塊做為作用域,因此 let name1 = 'Jack'
這個語法的有效範圍只會存在於 { ... }
之中,而 var
則會被 { ... }
中的 var name1 = 'Jack'
,直接做替換,因此 name1
會是 'Jack'
。
這邊要補充一下, 這邊提到的 { ... }
並不是物件,而是一個作用域範圍,主要是為了搭配 let
、 const
特性 ES6 才引入的,不過實做中通常不會刻意使用 { ... }
去區分作用域。
提升特性不同
在提升章節我們有提到,JavaScript 在編譯程式碼時,會分為兩個階段:
1.創造階段
2.執行階段var
變數會先在 創造階段 被建立,進入執行階段才會實際賦值,而在創造階段中的 var
變數,他的值會是 undefined
,如這個範例:
1 | console.log(name1) // undefined |
let
雖然也有提升概念,也同樣分成:
1.創造階段
2.執行階段
但在創造階段和 var
不同,let
在創造階段不是直接顯示 undefined
,他是進入一個 暫時性死區 (TDZ) 的狀況,MDN 文件是這麼描述的:
The variable is in a “temporal dead zone” from the start of the block until the initialization is processed
如果我們在 暫時性死區 的狀態去取得 let
變數的值,瀏覽器會跳錯,要注意的是,不同瀏覽器跳出的錯誤訊息會不同,如下範例:
FireFox 版本
1 | console.log(name2) // Uncaught ReferenceError: can't access lexical declaration 'name1' before initialization |
Chrome 版本
1 | console.log(name2) //Uncaught ReferenceError: name1 is not defined |
全域建立變數
上面有提到到 let
、 const
是根據 { ... }
來區分作用域的,這邊要提一點的是 var
全域建立時,會是掛在 window 下。
而使用 let
、 const
在全域建立變數時,他並不會掛在 window 下,但我們若直接呼叫變數,他也會正確顯示,如範例
1 | var name1= 'Ryder' |
這個原因是出在全域執行環境(Global space) 上面,首先這個全域執行環境其實是由兩個環境所組成的
- 全域物件 - Object Env
- 宣告環境 - Declare Env
因此全域執行環境(Global space) 其實是一個由雙環境組成的東西,一般來說我們是看不到 Declare Env 的。
所以 var
其實是基於 ObjectEnv 宣告並加入到 Declare Env,而 let
、const
則是只會宣告在 Declare Env 中,這也就是為什麼我們無法在 Window 上面看到由 let
、const
宣告的變數但卻又可以正常取得到值的原因。
參考文獻
- JavaScript 核心篇 (六角學院)
- MDN 文件 - 區塊
- 关于 const 和 let 声明的变量不在 window 上
- 淺談 var 與 let 的差異以及有無宣告變數的差異