本文主要是比較動態範疇與語彙範疇的差異。
前情提要,先前提過範疇是指編譯器或 JavaScript 引擎藉由識別字名稱(identifier name)查找變數的一組規則;而「語彙範疇」是指在語彙分析時期所定義的靜態範疇,且不經由 eval 或 with 在執行時的修改。語彙範疇考量的是變數「如何和何處被宣告」,其查找的範疇串鏈是以程式碼的巢狀結構為基礎。
範例如下,在 foo 中的 a 由於無法在所在函式 foo 內經由 RHS 解析得到 a 的值,因此會往全域範疇查找,因而得到 3。
function foo() {
console.log(a); // 3
}
function bar() {
var a = 2;
foo();
}
var a = 3;
bar();
相較之下,「動態範疇」是指在執行時期(runtime)動態地決定範疇,考量點是變數「何處被呼叫」,其查找的範疇串鏈是以呼叫堆疊(call stack)為基礎。
範例如下,同樣的, a 在 foo 中無法解析其值,因此循著 call stack 找到 foo 被呼叫的地方 bar,在 bar 內找到 a 的值為 2。
function foo() {
console.log(a); // 2
}
function bar() {
var a = 2;
foo();
}
var a = 3;
bar();
事實上,JavaScript 並沒有動態範疇,但 this 的查找規則是類似動態範疇的,在後續關於 this 的篇章會再詳細說明。
看完這篇文章,我們到底有什麼收穫呢?藉由本文可以理解到...
語彙範疇與動態範疇的主要差異在於,前者查找的範疇串鏈是以程式碼的巢狀結構為基礎,而後者則是以呼叫堆疊(call stack)為基礎。
同步發表於部落格。