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

閱讀時間約 6 分鐘
對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。
在 JavaScript ES6 中,let、const 取代了 var 作為新的宣告變數時使用的關鍵字,讓變數在被宣告時,可以更加嚴謹,因此在現行的專案中,大部分的人都是使用這來個關鍵字來宣告變數居多,不太會有需要使用到 var 的機會。
既然不太會使用到,為什麼我們依然要花時間理解,透過這三者來宣告變數的差異呢?這會有幾個主要的原因:
  1. 了解letconst 是為什麼解決什麼問題而存在
  2. junior front-end developer 必考的面試考題
  3. 不少舊的套件還是使用 var 作為範本
  4. 許多經典的前端書籍還維持在 var 的使用階段
  5. 未來你有可能會經手、接管、維護舊專案
因此,花一點時間來了解這個議題絕對很值得,接下來的內容中,主要會以下幾點來進行討論:
  1. 變數是否可以被重複宣告
  2. 變數是否可以被重新指值
  3. 變數作用域差異
  4. 變數 Hoisting 行為時的報錯訊息不同
  5. 變數是否強制在宣告時指定值
如果你還不曉得什麼是 ES5、ES6 的話,可以參考這篇文章:

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

ES6 以前還沒有 let、const 前,如果使用 var 關鍵字對同一個變數重複宣告是合法的,並不會報錯。
使用 var 重複宣告但不報錯的原理,就很像是我們可以針對同一個 CSS 類別下不同的樣式,而最下方的程式碼會覆蓋掉最上面的,但並不構成錯誤。
然而重複宣告變數,可能會造成開發者要取用變數時,很容易取到錯誤的值,程式碼會變得不好維護,所以在 ES6 以後,新增了 let、const 關鍵字作為替代。
我們會發現,在還沒有執行到 console.log(price) 時,程式碼就因為 price 變數被重複宣告而出現錯誤無法繼續執行。
同理,既然是為了修正以前 var 可以被重複宣告所造成的錯誤, const 關鍵字同樣不能拿來重複宣告變數。
結論:var 可以被重複宣告,但是 const、let 不行。

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

有時候為了要在函式中更新全域變數中的值,我們會在函式中重新指定一個新的值給全域變數。
但有時候我們不想要讓已經被宣告的變數,可以輕易地被改到值,這時候我們就可以使用 const 關鍵字來宣告變數。
使用 const 關鍵字可以避免一個變數重新被指定新值,如果有這樣的狀況的話,瀏覽器就會報錯:「Uncaught TypeError: Assignment to constant variable.」
結論:如果在宣告變數以後,還會有需求要重新指定值,那就使用 let 宣告變數;如果是固定的資料,像是資料夾位置、API 路徑等不能被輕易改動的內容,就需要使用 const 關鍵字來宣告。

變數作用域差異

作用域的差異可以說是 ES6 與 ES6 以前差異最多的部分,對於初學者來說,需要花一段時間來了解。
在 JavaScript 中變數有效的範圍,也就是可以被取用的範圍稱為作用域(Scope)。
以 var 來說,var 的作用域分為全域作用域及函式作用域,一個變數是否能被取用到,是以 function 來切分的。
在函式中想要讀出 a 變數值時,會優先查找函式內是否有名為 a 的變數,如果沒有的話才會向外查找。
但在 showVariable()函式中,已經有一個變數叫做 a 了,所以讀出來的結果就是「區域變數」。
但如果在函式外讀取,是取不到函式內變數 a 的值,只能取到做外層帶有「全域變數」值的 a 變數。
這裡看起來與 let、const 的使用情境無太大差異,讓我們再來看看另一個範例:
顯然在這個範例中,只用大括號包住的宣告,並沒有辦法達到區域作用域的功能,反而將 a 的值都覆寫過去了,讓兩邊的印出來的值都是「區域變數」,光這一點就能判斷 var 的作用域只會在全域及函式中出現。
而且只要是透過 var 宣告過的變數,便會成為全域屬性,造成全域污染的問題。
現在如果用 let 來取代 var 來宣告一樣的變數會發生什麼事呢?
這一個範例跟剛剛使用 var 宣告沒有兩樣。
但是我們可以發現 let 在 { } 中是可以自行創建出作用域的!
由此可知我們可以透過上方範例了解到,let、const 的作用域與 var 不一樣,屬於全域、區塊作用域。

變數 Hoisting 時的行為不同

let、const 作為 ES6 以後的語法,很嚴格的禁止「宣告前可以被取到值」的行為:
然而如果透過 var 來宣告的話:
會發現透過 var 宣告的變數不會報錯,而是出現 undefined 的值。
這裡做個小結:這三者都會有 hoisting 的行為,在宣告前就取用變數時,var 僅會回傳 undefined,但是因為 let、const 較嚴謹,所以會帶有錯誤訊息,MDN 文件稱這個現象為 TDZ(Temporal dead zone)。
由於 hoisting 行為需要一點篇幅解釋,希望之後在利用其他篇幅來跟大家介紹何謂 hoisting,又因這一篇為 let、const及var 的差異比較,故不多贅述。

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

const 在宣告時一定要指定值,不然會報錯。
但在使用 var 與 let 時,可以不用先指定值,可以後續在重新指定,這是基於透過 const 宣告的變數,會成為常數,所以不帶有重新指定值的特性。
基本上 let、const 與 var 的差異了解大概到這,希望下次碰到這個問題時,可以更有自信的講述這三者的差異性,即便開發上不太會用到,卻是能更了解這門語言的機會。
相信透過這篇文章,大家可以更加了解let、const 與 var 的差異,關於網頁開發你有沒有什麼問題想要跟我分享的呢?歡迎你在下方留言與我分享。
希望今天的文章有幫助到正在閱讀的你,如果你喜歡我的文章的話,可以留下你的愛心或是收藏我的文章,也或者可以點選「贊助」,你的一杯咖啡絕對是我持續寫下去的動力!或是透過拍拍手,用你小小的行動支持我的創作!
我是Vivian,我們下次見。
關於我:
一名從英文系畢業的前端工程師,喜歡閱讀、寫東西及自我成長。
|聯絡我:vivian.enlife@gmail.com
為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
在初學程式的時候,我曾經看室友開發專案到一半時,突然坐在那發呆,於是我好奇一問,室友說:「我在等程式編譯完成啊。」 還記得當初還是程式小菜雞的我,懞懂無知的說:「編譯?哈哈哈,我們 JavaScript 都不需要編譯耶,可以直接跑在瀏覽器上。」 室友一臉莫名其妙地回我:「噢,是嗎⋯⋯」
前陣子有讀者來信詢問我:「嗨!Vivian,我想要請問妳都是在哪裡學程式的呢?是實體課程嗎?」
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
在初學程式的時候,我曾經看室友開發專案到一半時,突然坐在那發呆,於是我好奇一問,室友說:「我在等程式編譯完成啊。」 還記得當初還是程式小菜雞的我,懞懂無知的說:「編譯?哈哈哈,我們 JavaScript 都不需要編譯耶,可以直接跑在瀏覽器上。」 室友一臉莫名其妙地回我:「噢,是嗎⋯⋯」
前陣子有讀者來信詢問我:「嗨!Vivian,我想要請問妳都是在哪裡學程式的呢?是實體課程嗎?」
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
在 JavaScript 中,變數是一個儲存值的容器,可用於管理和操作資料。變數可以透過 let、const 和 var 進行宣告。選擇適當的變數宣告方式是確保程式碼可讀性和可維護性的關鍵。
就是指變數可以被訪問和使用的範圍,來說一下var、let和const的作用域差異。 var :function example() { console.log(x); // 輸出: undefined 因為變量提升造成的 var x = 5; } 函數作用域或全域作用域 可以重複宣告
在 Solidity 中,constant 變量用於定義不可變的常數值。這些常數在合約的生命週期內不會改變,並且它們的值必須在宣告時設定。使用 constant 關鍵字可以節省 gas,因為它們在編譯時就已經被嵌入到字節碼中,不需要在運行時讀取存儲。 用法 定義常數: 常數變量必須在宣告時初始
Thumbnail
在本章節中,我們將學習JavaScript的基本語法,包括如何註解代碼和如何聲明變數。瞭解這些基礎知識對於進一步學習和使用JavaScript來編寫代碼是非常重要的。
※ ES6 變數宣告介紹: 在ES6中,推薦使用let和const取代原有的var來宣告變數。 ※ var的特點: 勢力範圍(scope)只有兩種:function、global(全域部分)。 勢力範圍(scope)指的是宣告變數的範圍,能夠被有效的使用的範圍。 可以在宣告變數之前就使用。
※ 函式基礎介紹: ※ JavaScript 特殊的函式特性: 函式可以當成值來傳遞 (可以放進變數或放進物件) 函式可以當成函式的參數 callback - 在特定事件中觸發函式 (非同步特性) ※ 函式的基本寫法: ※ 調用 (invoke) 函式: "調用" 意指呼叫或執行
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
Thumbnail
JS 資料型別分為兩大類,原始型別 (Primitive values) 和物件型別 (Objects)。
Thumbnail
在 CSS 的開發過程中,重複使用如顏色、字體大小等值是常見的需求。為了提高程式碼維護性和靈活性,就需要用到 CSS 變量了,CSS 變量可以讓你在樣式表中儲存可重用的值。本文將介紹 CSS 變量的概念、使用方法,以及它對撰寫 CSS 的影響。
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
在 JavaScript 中,變數是一個儲存值的容器,可用於管理和操作資料。變數可以透過 let、const 和 var 進行宣告。選擇適當的變數宣告方式是確保程式碼可讀性和可維護性的關鍵。
就是指變數可以被訪問和使用的範圍,來說一下var、let和const的作用域差異。 var :function example() { console.log(x); // 輸出: undefined 因為變量提升造成的 var x = 5; } 函數作用域或全域作用域 可以重複宣告
在 Solidity 中,constant 變量用於定義不可變的常數值。這些常數在合約的生命週期內不會改變,並且它們的值必須在宣告時設定。使用 constant 關鍵字可以節省 gas,因為它們在編譯時就已經被嵌入到字節碼中,不需要在運行時讀取存儲。 用法 定義常數: 常數變量必須在宣告時初始
Thumbnail
在本章節中,我們將學習JavaScript的基本語法,包括如何註解代碼和如何聲明變數。瞭解這些基礎知識對於進一步學習和使用JavaScript來編寫代碼是非常重要的。
※ ES6 變數宣告介紹: 在ES6中,推薦使用let和const取代原有的var來宣告變數。 ※ var的特點: 勢力範圍(scope)只有兩種:function、global(全域部分)。 勢力範圍(scope)指的是宣告變數的範圍,能夠被有效的使用的範圍。 可以在宣告變數之前就使用。
※ 函式基礎介紹: ※ JavaScript 特殊的函式特性: 函式可以當成值來傳遞 (可以放進變數或放進物件) 函式可以當成函式的參數 callback - 在特定事件中觸發函式 (非同步特性) ※ 函式的基本寫法: ※ 調用 (invoke) 函式: "調用" 意指呼叫或執行
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
Thumbnail
JS 資料型別分為兩大類,原始型別 (Primitive values) 和物件型別 (Objects)。
Thumbnail
在 CSS 的開發過程中,重複使用如顏色、字體大小等值是常見的需求。為了提高程式碼維護性和靈活性,就需要用到 CSS 變量了,CSS 變量可以讓你在樣式表中儲存可重用的值。本文將介紹 CSS 變量的概念、使用方法,以及它對撰寫 CSS 的影響。