此篇從幾個不同面向來探討 var、let、const 的差異。
科普
再開始之前先簡單科普幾個名詞,有助於理解後面篇幅內容。
Scope
白話文:程式碼的作用域。(想看 MDN 定義的請往這邊 scope)
編譯器或 JavaScript 引擎藉由 識別字名稱
(identifier name)去查找變數,查找的規則是依循 RHS、LHS,而 RHS、LHS
是有範圍限制的(如果沒有範圍限制,全部的都變成全域不就 GG 了),所以透過定義出了三種 scope type(global scope、function scope、block scope)來區分 RHS、LHS
的使用範圍。
更多 Scope 運作原理可以參考下方文章:
- summer 大大(超爆詳細):你懂 JavaScript 嗎?#12 函式範疇與區塊範疇(Function vs Block Scope)
Hoisting
白話文:將陳述式( Statement )提升(Hoisting),其特性使其在定義前,使用也可以運行。
下方圖片中左邊程式碼因為 Hoisting 特性
使其可以運行,其效果可以參考圖片中右邊程式碼,想像 Hoisting
就是將宣告的部分提升至最前面,使其在宣告前使用不會因為尚未定義
就噴 not defined。
TDZ
白話文:在 let、const 情況下
宣告後
以及尚未賦予值
前都無法取用,因為會進入 TDZ(暫時性死區中)。
下方圖片透過具象化方式來幫助理解暫時性死區
,範例中宣告時會進入 TDZ,當賦予值時才會離開。
科普就到這邊,下方開始會透過範例來解析 var、let、const 三者差異。
下方圖片是三者比較表,在後續的篇文中可以搭配範例一起服用。
var
var 作用域
僅限
於函式
。
若在其他區塊(ex:for、while、if)宣告 var,會被當成全域
使用。
1 | // function scope |
let
let 作用域在
{}、()
。
若在作用域外使用變數,會因為 TDZ 特性造成 Reference Error
。
1 | // block scope |
const
const 作用域在
{}、()
。
若在作用域外使用變數,會因為 TDZ 特性造成 Reference Error
,且宣告時必須
賦予值,否則會噴 SyntaxError
錯誤。
1 | console.log(msg); |
conclusion
三者最大差異是 作用域 Scope
。
最後用兩個問題來複習這篇文章,大家可以試著回答看看。
Q1:const 可不可以修改?
freeze()
,可以防止物件 reference 的 property 被更動。