前言
這篇文章主要是用來記錄理解 closure 的過程,scope 其實沒有很難懂的理論,但是整體非常的複雜,如果沒有專心推演每一個環節得話,像我這樣的初學者很容易小迷路。我也是這樣過來的,最後發現 Huli 老師在課堂中用的這段程式碼還蠻適合理解基礎的 closure 概念的,但是腦袋容量有限,想趁腦袋還搞得清楚時來記錄理解 closure 的推演邏輯。
以下就是本文章所要使用的程式碼:
function test(){
var a = 10;
function inner(){
console.log(a);
}
return inner
}
var func = test();
假裝你是 JavaScript 引擎
在接下來,我們會以自己是 JavaScript 引擎的角度,一步步建構各層的 execution context 還有 variable object(在 function 裡面的要改名叫 object,雖然兩個基本上是一樣的東西)。
global
- 引擎進到 global 的範圍裡,先找看看有沒有 variables 和 function。
- 找到了
function test()
以及變數func
,把他們兩個加進 variables object。
//object 裡面大概會長這樣
global{
variables object{
test: function,
func: undefined
}
}
- 程式開始執行,function test() 還未被呼叫先跳過。
- 在
var func = test();
test()
被呼叫,進入 test() 的範圍裡。v
function test()
- 進到 test() 的範圍裡,尋找看看有沒有 variables 或 function。
- 找到了 variable a 以及 function inner(),將他們加進 variable object 裡面。
//variable object 裡面大概長這樣
test{
variable object{
a: undefined,
inner: function
}
}
執行之後:
test{
variable object{
a: 10,
inner: function
}
}
test()
返回inner()
function。- 回到 global。
global
- 變數
func
等於test()
回傳的 functioninner()
。 test()
function 執行結束,所以test()
裡的 variable object 和 execution context 需要移除 -> X- 因為 global 裡面的變數
func
等於test()
裡面的inner()
,在未來如果呼叫了func
會用到inner()
和test()
裡的 variable object。所以test()
和inner()
的 variable object 會被存下來,以備不時之需。
用 node.js 的環境執行後,可以發現的確如上面所述,變數 a 的 變化全部都被引擎記下來,並沒有因為引擎已經跑完 test()
的環境而刪掉這些資訊。
這就是 closure 的行為。