var a = 'a';
say();
function say() {
console.log(a); // 輸出 undefined,而非 'a'
var a = 'b';
console.log(a); // 輸出 'b'
}
JavaScript 引擎在執行前會進行「編譯階段」,將所有 var 宣告(非賦值)提升至當前作用域頂部。上述代碼等價於:
var a = 'a';
function say() {
var a; // 宣告被提升,初始值為 undefined
console.log(a); // 此時訪問的是區域變量 a,值為 undefined
a = 'b'; // 賦值留在原處
console.log(a); // 輸出 'b'
}
say();
var a = 'b' 拆解為 var a;(提升)與 a = 'b';(留在原處)。var 無塊級作用域,僅在函數內提升至函數頂部。ReferenceError,建議開啟 'use strict';。ES6 引入的 let 與 const 具有塊級作用域,且存在「暫時性死區」(TDZ),在宣告前訪問會直接拋錯,從根源杜絕此類困惑:
let a = 'a';
say();
function say() {
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 'b';
}
理解變量提升機制是掌握 JavaScript 作用域的關鍵。實務開發中,請優先使用 const(不可重新指派)與 let(可重新指派),拒絕 var,讓程式碼行為更符合直覺、更易維護。