[第十六週]從簡單例子了解 closure (閉包)


Posted by Powerfultraveling 's Blog on 2021-07-31

前言

這篇文章主要是用來記錄理解 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

  1. 引擎進到 global 的範圍裡,先找看看有沒有 variables 和 function。
  2. 找到了 function test() 以及變數 func,把他們兩個加進 variables object。
//object 裡面大概會長這樣
global{
    variables object{
        test: function,
        func: undefined
    }
}
  1. 程式開始執行,function test() 還未被呼叫先跳過。
  2. var func = test(); test() 被呼叫,進入 test() 的範圍裡。v

function test()

  1. 進到 test() 的範圍裡,尋找看看有沒有 variables 或 function。
  2. 找到了 variable a 以及 function inner(),將他們加進 variable object 裡面。
//variable object 裡面大概長這樣
test{
    variable object{
        a: undefined,
        inner: function
    }
}

執行之後:

test{
    variable object{
    a: 10,
    inner: function
    }
}
  1. test() 返回 inner() function。
  2. 回到 global。

global

  1. 變數 func 等於 test() 回傳的 function inner()
  2. test() function 執行結束,所以 test() 裡的 variable object 和 execution context 需要移除 -> X
  3. 因為 global 裡面的變數 func 等於 test() 裡面的 inner(),在未來如果呼叫了 func 會用到 inner()test() 裡的 variable object。所以 test()inner() 的 variable object 會被存下來,以備不時之需。

用 node.js 的環境執行後,可以發現的確如上面所述,變數 a 的 變化全部都被引擎記下來,並沒有因為引擎已經跑完 test() 的環境而刪掉這些資訊。

這就是 closure 的行為。










Related Posts

1. Design Pattern

1. Design Pattern

滲透測試重新打底(1)--論Reconnaissance (偵查)

滲透測試重新打底(1)--論Reconnaissance (偵查)

所有的函式都是閉包:談 JS 中的作用域與 Closure

所有的函式都是閉包:談 JS 中的作用域與 Closure


Comments