【自學程式】var、let 與 const 到底差在哪?

更新 發佈閱讀 7 分鐘

對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。

在 JavaScript ES6 中,let、const 取代了 var 作為新的宣告變數時使用的關鍵字,讓變數在被宣告時,可以更加嚴謹,因此在現行的專案中,大部分的人都是使用這來個關鍵字來宣告變數居多,不太會有需要使用到 var 的機會。

既然不太會使用到,為什麼我們依然要花時間理解,透過這三者來宣告變數的差異呢?這會有幾個主要的原因:

  1. 了解let 與 const 是為什麼解決什麼問題而存在
  2. junior front-end developer 必考的面試考題
  3. 不少舊的套件還是使用 var 作為範本
  4. 許多經典的前端書籍還維持在 var 的使用階段
  5. 未來你有可能會經手、接管、維護舊專案

因此,花一點時間來了解這個議題絕對很值得,接下來的內容中,主要會以下幾點來進行討論:

  1. 變數是否可以被重複宣告
  2. 變數是否可以被重新指值
  3. 變數作用域差異
  4. 變數 Hoisting 行為時的報錯訊息不同
  5. 變數是否強制在宣告時指定值
如果你還不曉得什麼是 ES5、ES6 的話,可以參考這篇文章:




變數是否可以重複宣告(redeclare)

ES6 以前還沒有 let、const 前,如果使用 var 關鍵字對同一個變數重複宣告是合法的,並不會報錯。

raw-image

使用 var 重複宣告但不報錯的原理,就很像是我們可以針對同一個 CSS 類別下不同的樣式,而最下方的程式碼會覆蓋掉最上面的,但並不構成錯誤。

然而重複宣告變數,可能會造成開發者要取用變數時,很容易取到錯誤的值,程式碼會變得不好維護,所以在 ES6 以後,新增了 let、const 關鍵字作為替代。

raw-image

我們會發現,在還沒有執行到 console.log(price) 時,程式碼就因為 price 變數被重複宣告而出現錯誤無法繼續執行。

同理,既然是為了修正以前 var 可以被重複宣告所造成的錯誤, const 關鍵字同樣不能拿來重複宣告變數。

結論:var 可以被重複宣告,但是 const、let 不行。



變數是否可以被重新指值( reassign / mutate )

有時候為了要在函式中更新全域變數中的值,我們會在函式中重新指定一個新的值給全域變數。

raw-image

但有時候我們不想要讓已經被宣告的變數,可以輕易地被改到值,這時候我們就可以使用 const 關鍵字來宣告變數。

raw-image

使用 const 關鍵字可以避免一個變數重新被指定新值,如果有這樣的狀況的話,瀏覽器就會報錯:「Uncaught TypeError: Assignment to constant variable.」

結論:如果在宣告變數以後,還會有需求要重新指定值,那就使用 let 宣告變數;如果是固定的資料,像是資料夾位置、API 路徑等不能被輕易改動的內容,就需要使用 const 關鍵字來宣告。



變數作用域差異

作用域的差異可以說是 ES6 與 ES6 以前差異最多的部分,對於初學者來說,需要花一段時間來了解。

在 JavaScript 中變數有效的範圍,也就是可以被取用的範圍稱為作用域(Scope)。

以 var 來說,var 的作用域分為全域作用域及函式作用域,一個變數是否能被取用到,是以 function 來切分的。

raw-image

在函式中想要讀出 a 變數值時,會優先查找函式內是否有名為 a 的變數,如果沒有的話才會向外查找。

但在 showVariable()函式中,已經有一個變數叫做 a 了,所以讀出來的結果就是「區域變數」。

但如果在函式外讀取,是取不到函式內變數 a 的值,只能取到做外層帶有「全域變數」值的 a 變數。

這裡看起來與 let、const 的使用情境無太大差異,讓我們再來看看另一個範例:

raw-image

顯然在這個範例中,只用大括號包住的宣告,並沒有辦法達到區域作用域的功能,反而將 a 的值都覆寫過去了,讓兩邊的印出來的值都是「區域變數」,光這一點就能判斷 var 的作用域只會在全域及函式中出現。

而且只要是透過 var 宣告過的變數,便會成為全域屬性,造成全域污染的問題。

現在如果用 let 來取代 var 來宣告一樣的變數會發生什麼事呢?

raw-image

這一個範例跟剛剛使用 var 宣告沒有兩樣。

raw-image

但是我們可以發現 let 在 { } 中是可以自行創建出作用域的!

由此可知我們可以透過上方範例了解到,let、const 的作用域與 var 不一樣,屬於全域、區塊作用域。



變數 Hoisting 時的行為不同

let、const 作為 ES6 以後的語法,很嚴格的禁止「宣告前可以被取到值」的行為:

raw-image

然而如果透過 var 來宣告的話:

raw-image

會發現透過 var 宣告的變數不會報錯,而是出現 undefined 的值。

這裡做個小結:這三者都會有 hoisting 的行為,在宣告前就取用變數時,var 僅會回傳 undefined,但是因為 let、const 較嚴謹,所以會帶有錯誤訊息,MDN 文件稱這個現象為 TDZ(Temporal dead zone)。

由於 hoisting 行為需要一點篇幅解釋,希望之後在利用其他篇幅來跟大家介紹何謂 hoisting,又因這一篇為 let、const及var 的差異比較,故不多贅述。



變數是否強制在宣告時指定值

const 在宣告時一定要指定值,不然會報錯。

raw-image

但在使用 var 與 let 時,可以不用先指定值,可以後續在重新指定,這是基於透過 const 宣告的變數,會成為常數,所以不帶有重新指定值的特性。

raw-image

基本上 let、const 與 var 的差異了解大概到這,希望下次碰到這個問題時,可以更有自信的講述這三者的差異性,即便開發上不太會用到,卻是能更了解這門語言的機會。

相信透過這篇文章,大家可以更加了解let、const 與 var 的差異,關於網頁開發你有沒有什麼問題想要跟我分享的呢?歡迎你在下方留言與我分享。

希望今天的文章有幫助到正在閱讀的你,如果你喜歡我的文章的話,可以留下你的愛心或是收藏我的文章,也或者可以點選「贊助」,你的一杯咖啡絕對是我持續寫下去的動力!或是透過拍拍手,用你小小的行動支持我的創作!

我是Vivian,我們下次見。



關於我:

一名從英文系畢業的前端工程師,喜歡閱讀、寫東西及自我成長。

|Instagram: Vivian Yeh|vivian_enlife

|聯絡我:vivian.enlife@gmail.com

留言
avatar-img
留言分享你的想法!
avatar-img
Vivian Yeh - 跨領域轉職的軟體工程師
453會員
103內容數
為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
2024/05/23
與 cookie 相比,localStorage 與 sessionStorage 的機制相對單純,兩者皆是瀏覽器中的儲存空間,與 cookie 最大的不同在於:localStorage 與 ⋯⋯
Thumbnail
2024/05/23
與 cookie 相比,localStorage 與 sessionStorage 的機制相對單純,兩者皆是瀏覽器中的儲存空間,與 cookie 最大的不同在於:localStorage 與 ⋯⋯
Thumbnail
2024/05/22
在瀏覽器環境中有許多的儲存空間,想要查看這些空間的話,可以透過「chrome > Dev Tools > Application > Storage」即能進行查看。 瀏覽器內存空間的差異不僅常常被拿來被當作面試考題,在實務開發中更扮演舉足輕重的角色,今天就想透過這系列的文章深度了解這些瀏覽器內存⋯
Thumbnail
2024/05/22
在瀏覽器環境中有許多的儲存空間,想要查看這些空間的話,可以透過「chrome > Dev Tools > Application > Storage」即能進行查看。 瀏覽器內存空間的差異不僅常常被拿來被當作面試考題,在實務開發中更扮演舉足輕重的角色,今天就想透過這系列的文章深度了解這些瀏覽器內存⋯
Thumbnail
2024/02/20
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
2024/02/20
上一篇文章分享了 TypeScript 的定義、前端角色定位,如果你不是很確定「TypeScript 是什麼?」、「TypeScript 作為 JavaScript 的超集,在網頁開發扮演怎麼樣的角色?」這兩個問題的答案,建議可以回到上一篇先了解一下。
Thumbnail
看更多
你可能也想看
Thumbnail
今天會接續介紹 JS ES6 其他新穎的語法,物件解構(Object Destructuring)物件語法強化(Object Literal Enhancement)陣列解構(Array Destructuring)延展運算子(Spread Operator)。
Thumbnail
今天會接續介紹 JS ES6 其他新穎的語法,物件解構(Object Destructuring)物件語法強化(Object Literal Enhancement)陣列解構(Array Destructuring)延展運算子(Spread Operator)。
Thumbnail
在進入到 React 前端框架之前,幫讀者複習有關 JavaScript 的知識。此篇著重,JavaScript 的歷史、let & const & var 差異、樣板字面值( Template Literals )、箭頭函式( Arrow Function )JS ES6 一個非常重要的前置知識。
Thumbnail
在進入到 React 前端框架之前,幫讀者複習有關 JavaScript 的知識。此篇著重,JavaScript 的歷史、let & const & var 差異、樣板字面值( Template Literals )、箭頭函式( Arrow Function )JS ES6 一個非常重要的前置知識。
Thumbnail
JavaScript 的型別可以分為兩類,分別是原始型別與物件型別,這邊主要談的是 ES6 的寫法。值得注意的是,JavaScript 變數本身不帶有型別,值才有。
Thumbnail
JavaScript 的型別可以分為兩類,分別是原始型別與物件型別,這邊主要談的是 ES6 的寫法。值得注意的是,JavaScript 變數本身不帶有型別,值才有。
Thumbnail
Hoisting 可以說是 ES6 問世之後,去面試還是會爾偶被問到的面試考題,雖然 Hoisting 離 Modern JavaScript 的技術有點距離,實作上幾乎不太會用到,但透過了解 Hoisting 的概念,可以對這門語言有更深的了解與掌握度。
Thumbnail
Hoisting 可以說是 ES6 問世之後,去面試還是會爾偶被問到的面試考題,雖然 Hoisting 離 Modern JavaScript 的技術有點距離,實作上幾乎不太會用到,但透過了解 Hoisting 的概念,可以對這門語言有更深的了解與掌握度。
Thumbnail
對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。
Thumbnail
對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。
Thumbnail
JavaScript在ES6新增了let, const等宣告變數的方式,其中let, const是block scope的,而var則是function scope。
Thumbnail
JavaScript在ES6新增了let, const等宣告變數的方式,其中let, const是block scope的,而var則是function scope。
Thumbnail
this 是 JavaScript 的一個關鍵字,也是讓新手困擾許久的主題,今天讓我們用更簡單、直接的方式來了解 this。
Thumbnail
this 是 JavaScript 的一個關鍵字,也是讓新手困擾許久的主題,今天讓我們用更簡單、直接的方式來了解 this。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News