兩段代碼唯一差別在於是否包含 s = &t; 語句,卻導致完全不同的輸出。這經典案例揭示了 JavaScript 變量聲明提升 與 作用域鏈 的核心機制。
// 版本 A:無 s = &t;
function foo() {
console.log(t); // undefined
var t = 10;
console.log(t); // 10
}
// 版本 B:有 s = &t;
function bar() {
console.log(t); // ReferenceError: t is not defined
s = &t; // 偽代碼,實為某種綁定/引用操作
var t = 10;
}
關鍵差異:版本 A 中 var t 被提升至函數頂部(初始化為 undefined),故第一行打印 undefined。版本 B 中 s = &t 在聲明前嘗試訪問 t 的引用,因 t 尚未在作用域中創建(暫時性死區 TDZ 效應),直接拋出 ReferenceError。
undefined。let/const 及某些引用操作會讓變量在聲明前處於 TDZ,訪問即報錯。s = &t 類似創建引用/指針,強制在聲明前解析 t 的內存地址,觸發 TDZ 檢查。(原答案附帶圖片展示作用域鏈與內存模型,此處用文字描述)
版本 A 執行流:
1. 創建 AO (Activation Object): { t: undefined }
2. console.log(t) -> undefined
3. t = 10
4. console.log(t) -> 10
版本 B 執行流:
1. 創建 AO: { t: } // 因 &t 引用標記為未初始化
2. console.log(t) -> ReferenceError: t is not defined
let/const 替代 var,利用 TDZ 早期發現邏輯錯誤。'use strict') 下部分隱式全局變量賦值會報錯,進一步規範代碼。理解變量提升與 TDZ,是寫出健壯 JavaScript 代碼、避免難以調試的「莫名其妙」輸出差異的基石。