JavaScript 的 Scope Chain 和 Outer Environment
前言
在執行環境介紹筆記中有提到, JavaScript 會在運行時建立執行環境(Execution Contexts),並將函式存進記憶體、為變數預留記憶體位置。需要注意的是,包在函式 {}
裡面的變數或函式,要等到函式被呼叫、建立執行函式執行環境時,才會被存進記憶體中。
範例
範例一
在這個範例中一共建立了三個執行環境,分別是: 全域執行環境、a 函式執行環境、b 函式執行環境。從範例中可以看出,同樣一個變數在不同的執行環境做宣告,他的值是獨立存在、不會互相影響的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function b() {
var myVar = 3
console.log(myVar)
}
function a() {
var myVar = 2
b()
}
var myVar = 1
a()
console.log(myVar)
// 輸出結果:
// 3
// 1範例二
這個範例和上個範例幾乎相同,唯一的差別是: b 函式裡面的myVar
沒有進行宣告,直接賦值。按照範例一的結果,變數的作用域應該是獨立於各個執行環境的,但我在 b 函式裡面的賦值動作卻操作到全域執行環境的 myVar?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function b() {
myVar = 3
console.log(myVar)
}
function a() {
var myVar = 2
b()
}
var myVar = 1
a()
console.log(myVar)
// 輸出結果:
// 3
// 3範例三
這個範例和前面範例的差異也不大: b 函式裡面的沒有進行任何myVar
宣告和賦值。在這種情況下,原本預期的輸出結果會出現undefined
,但是這邊卻印出了全域myVar
的值?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function b() {
console.log(myVar)
}
function a() {
var myVar = 2
b()
}
var myVar = 1
a()
console.log(myVar)
// 輸出結果:
// 1
// 1
Outer Environment
上面範例中狀況其實是由一個 JavaScript 的特性造成的。如果要使用一個當前執行環境(execution context)所沒有的變數時, JavaScript 會去 Outer Environment 尋找。但 Outer Environment 到底是指什麼呢?
在執行環境介紹筆記中有提到,在函式執行環境的創建階段,除了會建立環境物件(內含被宣告的變數和函式),還有一個叫做外部環境(Outer Environment)的東西會被一併設定好。外部環境可以用函式(function)被「宣告」的執行環境來判斷(注意! 不是函式被執行所建立的執行環境)。
以範例二和範例三來看,執行環境和函式的宣告關係如下:
Execution Contexts | Declare in memory | Outer Environments |
---|---|---|
Global | function a 、 function b 、 myVar | N/A |
function a | myVar | Global |
function b | N/A | Global |
因為在範例二和範例三中,function b
並沒有宣告 myVar
,所以當 function b
要用到 myVar
這個變數時, JavaScript 會到 function b
的外部環境,也就是全域執行環境(Global Execution Contexts)找到 myVar
來使用。
如果用函式被「宣告」的執行環境來判斷外部環境不容易理解的話,也可以用 Lexical Envirenments 來判斷,也就是函式被書寫的位置。如果函式寫在 Global 層級,那它的外部環境就是 Global;如果函式寫在另一個函式裡面,那它的外部環境就是一個函式。
- 範例四
如果把 function b 移到 function a 裡面宣告。如果用範例四來判斷外部環境,會呈現下面表格說明的關係:1
2
3
4
5
6
7
8
9
10function a() {
function b() {
var myVar = 3
}
var myVar = 2
b()
}
var myVar = 1
a()Execution Contexts Declare in memory Outer Environments Global function a 、 myVar N/A function a function b 、 myVar Global function b myVar function a
Scope Chain
Scope Chain 其實就是一個函式(function)向上追蹤外部環境(Outer Environments),直到找到全域執行環境為止所有的執行環境。
以範例四來說,整條 Scope Chain 就是: function b —> function a —> Global 。
參考資料
文章內容如有錯誤,歡迎留言討論!
本 Blog 上的所有文章除特别聲明外,均採用 CC BY-SA 4.0 協議 ,轉載請註明出處!