【JavaScript】變數宣告 const、let、var 的差異

【JavaScript】變數宣告 const、let、var 的差異

本篇重點

  • constlet 採用 Block Scopevar 採用 Function Scope
  • const 不允許 Reassignment,但不代表其參照的物件 Immutable
  • letconst 具有 Temporal Dead Zone (TDZ)var 則會在 Scope 建立時初始化為 undefined
  • letconst 在同一 Scope 不允許 Redeclarationvar 可以
  • 現代 JavaScript 通常以 const 為預設,需要重新賦值時使用 let
  • var 在新專案、新程式碼通常不再使用

constlet 都是 ES6 引入的 Block Scope 宣告方式,與較早存在的 var 在 Scope、Reassignment、Redeclaration 及 Hoisting 行為上都有明顯差異。

健忘筆記

ES6(正式名稱為 ES2015)是 JavaScript 發展史上最大的一次改版,導入了 class、箭頭函式、let/const、Promise 等現代開發不可或缺的基礎語法,因此現代 JavaScript 常常以 ES6 稱呼,但其實一直有發佈新版本,可到 w3schools 查看資訊。

特性constletvar
ScopeBlock ScopeBlock ScopeFunction Scope
Reassignment不允許允許允許
同一 Scope Redeclaration不允許不允許允許
Hoisting有宣告效果,但受 TDZ 限制有宣告效果,但受 TDZ 限制宣告會被 Hoist,初始值為 undefined
TDZ
必須初始化
現代程式碼優先使用需要重新賦值時使用通常避免

健忘筆記

宣告(Declaration)
告訴 JS:「我要建立一個叫 age 的變數。」,例:let age;

初始化(Initialization)

  • 變數第一次取得值,例:let age = 18;
  • 這裡同時完成「宣告 + 賦值」。

賦值(Assignment)

  • 把某個值指定給變數,例:age = 20;
  • 如果變數已經有值,叫「重新賦值(Reassignment)」。

Scope 機制

Block Scope

區塊作用域

letconst 遵循區塊作用域規範。變數只在大括號 {} 包覆的區域內有效,包含 if 判斷式、for 迴圈以及獨立的程式碼區塊。當執行流程離開這個區塊後,區塊內宣告的變數就無法再被使用,換句話說,區塊內宣告的變數即離開作用域並釋放記憶體。

Function Scope

函式作用域

var 遵循函式作用域。在函式內部宣告,變數作用域擴展至整個函式體;在函式外宣告,則成為全域變數(在瀏覽器環境下會掛載於 window 物件上)。var 完全忽略 iffor 等區塊邊界,所以容易造成變數覆蓋與全域污染。

js
1
2
3
4
5
6
7
8
9
10
11
12
13
function scopeExample() {
let a = 1;
const b = 2;
var c = 3;

console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
}

console.log(a); // ReferenceError
console.log(b); // ReferenceError
console.log(c); // 3

Reassignment 與 Redeclaration

  • Reassignment:重新指定既有變數的值。
  • Redeclaration:再次使用宣告關鍵字建立同名變數。

let:禁止在同一作用域內重複宣告,但允許重新賦值。

js
1
2
3
let count = 1;
count = 2; // Reassignment:允許
let count = 3; // Redeclaration:不允許(SyntaxError)

const:宣告時必須立即 Initialization(初始化),之後完全禁止重新賦值,並且禁止在同一作用域內重複宣告。

js
1
2
3
const count = 1;
count = 2; // Reassignment:不允許(TypeError)
const count = 2; // Redeclaration:不允許(SyntaxError)

const 限制變數本身不能被重新賦值,不限制變數所參照的資料內容

範例

js
1
2
3
4
5
const user = {
name: "Alice"
};
user.name = "Bob"; // 允許
user = {}; // TypeError

user 參照同一個物件,因此可以修改物件的屬性,但不能讓 user 改為參照另一個物件。

健忘筆記

const 不可重新賦值,但不等於 Value Immutable。
若需要真正限制物件內容,不能單靠 const ,需用 Object.freeze();來達成。

var:允許在同一作用域內重複宣告相同名稱的變數,且支援任意次數的重新指派,因此在大型專案中較容易產生非預期行為。

js
1
2
3
var count = 1;
var count = 2; // Redeclaration:允許
count = 3; // Reassignment:允許

Hoisting

var:Hoisting 階段同時完成「宣告」與「初始化為 undefined

js
1
2
3
console.log(value); // undefined

var value = 10;

可以想像成:

js
1
2
3
4
var value;
console.log(value);

value = 10;

let / const:Hoisting 階段僅完成「宣告」,並未進行「初始化」,到宣告前處於 Temporal Dead Zone (TDZ)

js
1
2
3
console.log(value); // ReferenceError

let value = 10; // 執行至此行,TDZ 結束並完成初始化

健忘筆記

暫時性死區 (Temporal Dead Zone, TDZ)
從作用域進入開始到該變數的宣告行之間,該變數處於暫時性死區(TDZ),確保變數在尚未確定值之前無法使用。在此區域內嘗試讀取或寫入該變數,JavaScript 會拋出 ReferenceError。

現代宣告的最佳實踐

  1. 預設使用 const:所有變數宣告皆優先採用 const,確保變數參考不被意外覆蓋,降低程式狀態變更的不確定性。
  2. 僅在需要重新指派時改用 let:例如迴圈計數器、狀態切換或需要延遲賦值的變數。
  3. 完全禁止使用 var:為避免作用域溢出、變數提升異常與全域污染問題,現代程式碼庫應藉由 ESLint 規則(no-var)全面禁止使用 var

差異總整理

項目constletvar
ScopeBlockBlockFunction
重新賦值
重複宣告
宣告前存取TDZ → ErrorTDZ → Errorundefined
必須初始化
現代 JavaScript首選必要時使用通常避免
使用情境不需 Reassignment 的變數需要 Reassignment 的變數Legacy Code

結論

constletvar 的核心差異在於 Scope(區塊 vs 函式)。var 具備自動初始化為 undefined 與無區塊邊界的特性,容易引入難以追蹤的 bug。現代 JavaScript 開發應嚴格遵循「const 優先、次選 let、全面停用 var」的原則,運用強約束性提升程式碼的可預測性與維護品質。

延伸閱讀

發表於

2026-09-03

更新於

2026-09-03

許可協議


你可能也想看

【PHP、JavaScript】陣列自定義排序
【Tool】Unix 時間戳(Unix timestamp)轉換
【PHP、JavaScript】三種實用的符號運算子 ?:、??、??=

評論

複製完成