19.js中閉包

js中閉包
    var name = "Microsoft";
    function funcA(){
        var name = "Google";
        alert(name);
        return function(){
        name = "Facebook";
        alert(name);
        };
    }
    var o = funcA(); //Google
    alert(name); //Microsoft
    o(); //Facebook
    ******************
        執行完後,執行流就會離開funcA, 那麼funcA的變量對象就應該被銷燬了。
        作用域鏈的創建規則是複製上一層環境的作用域鏈,並將指向本環境變量對象的指針放到鏈首;
    ******************
    匿名函數的作用域鏈應該有三個元素,第一個是匿名函數的變量對象指針,第二個是funcA的變量對象指針,第三個是全局變量對象指針。根據搜索算法,首先搜索匿名函數的變量對象,顯然這個對象中不存在name,然後搜索funcA的變量對象,這裏面有個“name”,因此將其作爲name變量返回,搜索終止,所以,匿名函數引用的是funcA內定義的“name”變量而非全局變量。
    var o = funcA();
    執行完後,執行流就會離開funcA, 那麼funcA的變量對象就應該被銷燬了,funcA內定義的變量name就應該不存在了,爲什麼在後面還可以訪問到呢?要解釋這個問題,請回想上文一句話:作用域鏈的創建規則是複製上一層環境的作用域鏈,並將指向本環境變量對象的指針放到鏈首;根據這句話我們知道匿名函數的作用域鏈有三個元素,引用了三個變量對象(上文有說),這裏要注意,返回的匿名函數賦值給了變量o,而變量o是一個全局變量,在funcA執行完成後不會被銷燬。當賦值的時候,匿名函數的作用域鏈已然建立,並且此作用域鏈引用了funcA的變量環境,因此,當funcA執行完畢後,其執行變量和作用域鏈確實被銷燬了,但是其變量對象沒有被銷燬,因爲匿名函數的作用域鏈對其有引用,其無法被垃圾回收機制銷燬。當funcA執行完成後funcA的Scope chain早就銷燬了,但是其變量對象(紅色表示),因爲被匿名函數的Scope chain引用了,所以沒有銷燬。因此,匿名函數可以訪問其成員,當匿名函數執行完成後,它會連同匿名函數的Scope chain一起被銷燬。
    閉包就是能訪問另一個函數作用域中變量的函數。
    因爲閉包通常通過匿名函數實現,所以經常有人將閉包和匿名函數兩個名詞混用。閉包的優點很明顯,就是可以訪問另一個函數域中的變量,缺點也明顯,比較耗內存(因爲同時保持了N個變量對象)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章