三個閉包實例理解閉包對內存的影響

在試圖弄清這個問題以前,先要理解棧內存、堆內存和預處理javascript

佔用內存,不會銷燬的閉包實例

例1:

var num = 12;
function fn() {
    var num = 100;
    return function () {
        console.log(num);
    }
}
var f = fn();
f();

例1的圖示java

未被佔用的堆內存纔會被銷燬git

因此,正如圖中橢圓形關鍵點中說明的那樣,堆內存xxxfff111被返回給了全局變量f,而全局變量只有在窗口關閉的時候纔會銷燬,所以堆內存xxxfff111將一直被佔用而不會銷燬,定義它的局部做用域A也不會被銷燬。github

例2

var oDiv = document.getElementById("div1");
~function() {
    oDiv.onclick = function() {

    }
}();

這段代碼的特色是:私有做用域給DOM元素的事件綁定一個方法。閉包

例2的圖示:函數

正如圖中橢圓形關鍵點所說,標籤對象的屬性裏面會自帶一個onclick的屬性,未被賦值時其值爲null。那麼,在自執行函數執行的時候,其建立的做用域所佔用的堆內存xxxfff111一樣也會被全局的堆內存xxxfff000佔用(這裏要注意,是堆內存佔用堆內存),因此堆內存xxxfff111和棧內存A都不會被銷燬。spa

不佔用內存,當即銷燬的實例

只須要將例1稍做修改。設計

例3:

function fn(){
    var num = 100;
    return function(){
        console.log(num);
    }
}
fn();    //主要修改在這裏

例3的圖示code

因爲在函數fn中,xxxfff111是被return的,因此棧內存A的預解釋不會處理xxxfff111,它只在fn函數執行的時候纔會生成,而函數fn的棧內存A每次被執行以後都會被銷燬。對象

暫時佔用內存,延時銷燬的閉包實例

將例3稍做修改,就變成了延時銷燬的閉包實例。

例4:

function fn(){
  var num = 100;
  return function(){

  }
}
fn()();    //這裏到底發生了什麼?實際上是執行了一次fn以後,把返回的子函數有執行了一次,因此在子函數執行的時候,棧內存fn()是不能銷燬的,可是子函數執行完畢後由於沒有被佔用,因此最終fn()仍是會被銷燬的。

例4的圖示:

正如圖中橢圓形關鍵點處所說,fn()()的意思是在執行完fn()以後再把返回的值函數執行一遍。所以在子函數執行的時候,堆內存xxxfff111被佔用了,相應的棧內存A也將保留。

可堆內存xxxfff111中保存的子函數在執行完成以後仍是會被銷燬,接着堆內存xxxfff111就做爲未被佔用的堆內存而被銷燬,最終棧內存A也會被銷燬。

因此,棧內存在執行完以後會被保留一段時間,這段時間等於其子函數執行的時間。

參考資料:

JavaScript高級程序設計(第三版)。

我在github
https://github.com/zhuanyongx...

相關文章
相關標籤/搜索