徹底弄懂 JavaScript 閉包

蕭瀟發表於2017-07-16

基礎概念

什麼是閉包

簡單來說,閉包是指可以訪問另一個函式作用域變數的函式,一般是定義在外層函式中的內層函式。

為什麼需要閉包呢

區域性變數無法共享和長久的儲存,而全域性變數可能造成變數汙染,所以我們希望有一種機制既可以長久的儲存變數又不會造成全域性汙染。

特點
  • 佔用更多記憶體
  • 不容易被釋放
何時使用

既想反覆使用,又想避免全域性汙染

如何使用

1.定義外層函式,封裝被保護的區域性變數。
2.定義內層函式,執行對外部函式變數的操作。
3.外層函式返回內層函式的物件,並且外層函式被呼叫,結果儲存在一個全域性的變數中。

函式生命週期

直接上圖,點選圖片放大檢視。要記住函式物件、作用域鏈物件、執行環境(EC)和活動物件(AO)這幾個東西都啥時候出現,啥時候消失。

函式生命週期

例子實戰

看下面這個函式,函式物件的地址僅作標識,不代表真實的地址。

var getNum;//------------------------1
function getCounter() { // ----------2
    var n = 1; 
    var inner = function () { return n++; }
    return inner;
}

getNum = getCounter();//------------3
console.log(getNum()); //1 ---------4
console.log(getNum()); //2 ---------5

程式執行到2的時候:

執行到2

程式執行到3的時候:

執行到3

執行到4的時候,外層函式呼叫結束,AO物件釋放,圖中紅線斷了:

4處的程式碼執行前

4處的程式碼執行時:

執行4處的程式碼

4處的程式碼執行完:

4處程式碼執行完

總結:可以看到內層函式物件被全域性的變數getNum引用,所以內層函式相關的AO物件,作用域鏈物件在函式呼叫完都無法被記憶體回收,因此佔用了更多的記憶體空間,但是這樣持久的儲存了需要的n

相關文章