本篇重點
const、let採用 Block Scope,var採用 Function Scopeconst不允許 Reassignment,但不代表其參照的物件 Immutablelet、const具有 Temporal Dead Zone (TDZ) ;var則會在 Scope 建立時初始化為undefinedlet、const在同一 Scope 不允許 Redeclaration;var可以- 現代 JavaScript 通常以
const為預設,需要重新賦值時使用let var在新專案、新程式碼通常不再使用
const、let 都是 ES6 引入的 Block Scope 宣告方式,與較早存在的 var 在 Scope、Reassignment、Redeclaration 及 Hoisting 行為上都有明顯差異。
| 特性 | const | let | var |
|---|---|---|---|
| Scope | Block Scope | Block Scope | Function Scope |
| Reassignment | 不允許 | 允許 | 允許 |
| 同一 Scope Redeclaration | 不允許 | 不允許 | 允許 |
| Hoisting | 有宣告效果,但受 TDZ 限制 | 有宣告效果,但受 TDZ 限制 | 宣告會被 Hoist,初始值為 undefined |
| TDZ | 有 | 有 | 無 |
| 必須初始化 | 是 | 否 | 否 |
| 現代程式碼 | 優先使用 | 需要重新賦值時使用 | 通常避免 |
Scope 機制
Block Scope
區塊作用域
let 與 const 遵循區塊作用域規範。變數只在大括號 {} 包覆的區域內有效,包含 if 判斷式、for 迴圈以及獨立的程式碼區塊。當執行流程離開這個區塊後,區塊內宣告的變數就無法再被使用,換句話說,區塊內宣告的變數即離開作用域並釋放記憶體。
Function Scope
函式作用域
var 遵循函式作用域。在函式內部宣告,變數作用域擴展至整個函式體;在函式外宣告,則成為全域變數(在瀏覽器環境下會掛載於 window 物件上)。var 完全忽略 if 或 for 等區塊邊界,所以容易造成變數覆蓋與全域污染。
1 | function scopeExample() { |
Reassignment 與 Redeclaration
- Reassignment:重新指定既有變數的值。
- Redeclaration:再次使用宣告關鍵字建立同名變數。
let:禁止在同一作用域內重複宣告,但允許重新賦值。
1 | let count = 1; |
const:宣告時必須立即 Initialization(初始化),之後完全禁止重新賦值,並且禁止在同一作用域內重複宣告。
1 | const count = 1; |
const 限制變數本身不能被重新賦值,不限制變數所參照的資料內容。
範例
1 | const user = { |
user 參照同一個物件,因此可以修改物件的屬性,但不能讓 user 改為參照另一個物件。
var:允許在同一作用域內重複宣告相同名稱的變數,且支援任意次數的重新指派,因此在大型專案中較容易產生非預期行為。
1 | var count = 1; |
Hoisting
var:Hoisting 階段同時完成「宣告」與「初始化為 undefined」
1 | console.log(value); // undefined |
可以想像成:
1 | var value; |
let / const:Hoisting 階段僅完成「宣告」,並未進行「初始化」,到宣告前處於 Temporal Dead Zone (TDZ)
1 | console.log(value); // ReferenceError |
現代宣告的最佳實踐
- 預設使用
const:所有變數宣告皆優先採用const,確保變數參考不被意外覆蓋,降低程式狀態變更的不確定性。 - 僅在需要重新指派時改用
let:例如迴圈計數器、狀態切換或需要延遲賦值的變數。 - 完全禁止使用
var:為避免作用域溢出、變數提升異常與全域污染問題,現代程式碼庫應藉由 ESLint 規則(no-var)全面禁止使用var。
差異總整理
| 項目 | const | let | var |
|---|---|---|---|
| Scope | Block | Block | Function |
| 重新賦值 | ❌ | ✅ | ✅ |
| 重複宣告 | ❌ | ❌ | ✅ |
| 宣告前存取 | TDZ → Error | TDZ → Error | undefined |
| 必須初始化 | ✅ | ❌ | ❌ |
| 現代 JavaScript | 首選 | 必要時使用 | 通常避免 |
| 使用情境 | 不需 Reassignment 的變數 | 需要 Reassignment 的變數 | Legacy Code |
結論
const、let 與 var 的核心差異在於 Scope(區塊 vs 函式)。var 具備自動初始化為 undefined 與無區塊邊界的特性,容易引入難以追蹤的 bug。現代 JavaScript 開發應嚴格遵循「const 優先、次選 let、全面停用 var」的原則,運用強約束性提升程式碼的可預測性與維護品質。



