深刻理解javascript系列(八):閉包(2)

本次筆記主要記錄了:bash

閉包與垃圾回收機制的關係,微信

閉包與做用域鏈的關係。閉包

8.1  閉包與垃圾回收機制

在系列(二)中,我提到了垃圾回收機制,知道當一個值失去引用以後就會被標記,而後被垃圾回收機制回收並釋放空間。函數

咱們知道,當一個函數的執行上下文運行完畢以後,內部全部內容都會失去引用而被垃圾回收機制回收。性能

咱們還知道,閉包的本質就是在函數外部保持了內部變量的引用,所以很明顯閉包會阻止垃圾回收機制回收。學習

下面咱們就用一個例子來證實這一點。ui

function f1() {
    var n = 999;
    nAdd = function() {
        n += 1;
    }

    return function f2() {
        consloe.log(n);
    }
}
var result = f1();
result();  //999
nAdd();
result();  //1000複製代碼

從上面的例子能夠看出,由於nAdd、f2都訪問了f1中的n,所以它們都與f1造成了閉包。這個時候變量n的引用被保留了下來。由於f2與nAdd執行時都訪問了n,而nAdd每運行一次就會將n加1.spa

認識到閉包中保存的內容不會被釋放以後,咱們就應該謹慎使用閉包。由於誰都知道,閉包的濫用可能會致使內存泄露於是影響程序性能。code

8.2  閉包與做用域鏈

在開始以前,先思考一個問題,閉包會致使函數的做用域鏈發生改變嗎?cdn

咱們結合下面的例子來分析一下。

var fn = null;
function foo() {
    var a = 2;
    function innerFoo() {
        console.log(a);
    }
    fn = innerFoo;    // 將innerFoo的引用賦值給全局變量中的fn
}
function bar() {
    fn();  //此處保留innerFoo的引用
}
foo();
bar(); //2複製代碼

在這個例子中,foo內部的innerFoo訪問了foo的變量a。所以當innerFoo執行時會有閉包產生,這是一個比較簡單的閉包的例子。不同的地方在與全局變量fn。fn在foo內部獲取了innerFoo的引用,並在bar中執行。

那麼innerFoo的做用域鏈會是怎麼樣的呢?


在這裏須要特別注意的地方是函數調用棧與做用域鏈的區別:

由於call stack實際上是在代碼執行時才肯定的,而做用域的規則在代碼編譯階段就已經肯定了。雖然做用域鏈的在代碼執行時才生成的,可是他的規則不會隨着代碼執行而發生變化。

so,這裏的閉包的存在並不會致使做用域鏈發生變化。

這些都是我以往的學習筆記。若是您看到此筆記,但願您能指出個人錯誤。有這麼一個羣,裏面的小夥伴互相監督,堅持天天輸出本身的學習心得,不輸出就出局。但願您能加入,咱們一塊兒終身學習。歡迎添加個人我的微信號:Pan1005919589

相關文章
相關標籤/搜索