一次搞懂 var、let、const 三種變數


變數(variable)讓數值得以重複使用,在 ES6 以前版本的 JavaScript 中,僅有「var」這個變數,但因有區塊作用域(block scope)的問題,ES6 起便新增「let」與「const」兩種變數。

以下分別以「再宣告」、「再賦值」、「初始化」、「提升」、「全域作用域」、「函式作用域」與「區塊作用域」七個角度比較 var、let 與 const 三種變數:

再宣告(re-declaration)

「宣告(declaration)」就像是「創造」變數,在宣告之前,這個變數並不存在,而「再宣告」則是指創造這個變數兩次,還會取代原本舊有的變數。

在同一執行環境內,var 允許變數再次宣告,但 let 與 const 皆不行,代表只要做出了 let 或 const,這個變數就在那邊,沒有辦法做一個新的 let 或 var 變數將其取代。


再賦值(re-assignment)

把變數做出來後,還要告訴變數它的值應該要是多少,這個「賦與變數一個值」的過程稱為「賦值(assignment)」。

在同一執行環境內,var 跟 let 都允許「再賦值」,也就是把變數做出來之後,裡面的內容可以更動;但 const 只要經過賦值,就無法更動其內容。


初始化(initialization)

初始化即為第一次的賦值,也就是在一個變數被做出來後、還沒有任何內容時,丟一個值給它。

let 跟 var 都可以不經初始化直接使用,未賦值者將回傳「undefined」,告訴我們這個變數確實存在,只是內部內容未被定義;const 則一定要完成初始化,沒有告訴這個變數它的值是多少就無法使用。


提升(hoisted)

在執行環境的創建階段中,記憶體會先分配給「函式宣告(function declaration)」與 var 變數,意即在實際讀到程式碼內容前,就可以先知道兩者的存在。

let、const 與「函數表達式(function expression)」皆無法提升,沒有辦法先執行、再說明三者實際內容為何。

事實上,let 與 const 也都可以提升,但不會被初始化為「undefined」,而是被放到暫時死區(temporary dead zone, TDZ),直到被賦值為止,在「被提升」與「被賦值」的過程之間存取,就會顯示錯誤,詳細可參考我知道你懂 hoisting,可是你了解到多深?

補充:函式的提升


僅函式宣告可被提升,在全域執行環境的創建階段就被預留好記憶體空間


全域作用域(global scope)

若一變數具有「全域作用域」,代表變數被放在全域執行環境創建階段的「全域物件」中,在整個程式碼各處、不論函式內外都能使用。var、let 與 const 三種變數皆有此性質。

在下圖的範例中,分別宣告 var、let、const 三變數為「program」、並賦值為「JavaScript」,下方外層函式「Learn1()」與內層函式「Learn2()」皆能夠讀取。


函式作用域(function scope)

若一變數具有「函式作用域」,代表該變數適用範圍僅限於宣告的函式內,函式外無法讀取該變數,var、let 與 const 三種變數皆有此性質。

在下圖的範例中,分別以 var、let、const 在「Learn1()」函式範圍內,宣告一變數為「instrument」、並賦值為「piano」,實際執行時,不論使用 var、let 還是const,位在「Learn1()」函式內的「Learn2()」函式皆無法讀取被宣告為「instrument」的變數。


區塊作用域(block scope)

「區塊作用域」代表變數適用範圍僅限於大括弧「{}」內,通常為搭配「迴圈」或「條件判斷」的敘述。

var 變數不具有區塊作用域,意即就算不是在與該變數宣告範圍同區域處,也會被 var 影響,例如若只想在某個迴圈中宣告 var 並賦值,但這個 var 會連帶影響迴圈外的其他 var 變數,跟這個迴圈無關的 var 也都會被拖下水。


總結來說,var 變數具有下列缺點:

  1. 允許重複宣告,新宣告的var會取代舊有的。
  2. 不具有區塊作用域,會讓不希望其發生作用的區域一併受到牽連。

在 ES6 之後,有了 let 與 const 兩種新變數解決上述兩問題,讓變數不會被重複宣告,也具備區塊作用域,較能精準掌握變數的作用範圍,而 let 與 const 兩者的最大差別在於是否可以重複賦值,因此可區別使用時機如下:

  1. 會重複賦值(如跑迴圈讓值不斷改變):let
  2. 不重複賦值(說它是什麼就是什麼,不希望被改):const

變數比較表

#javascript #變數 #let #const #var







你可能感興趣的文章

ASP.NET Core Web API 入門教學 - 使用AutoMapper自動對應Dto欄位

ASP.NET Core Web API 入門教學 - 使用AutoMapper自動對應Dto欄位

3. 提升 ( Hoisting )

3. 提升 ( Hoisting )

SQL 資料處理

SQL 資料處理






留言討論