2017-02-26 29 views
0

我敢肯定這已被問過,但我沒有找到它。Javascript關閉內存使用與對象成員

什麼是下面的示例JavaScript關閉內存使用情況:

var f = (function(sz){ 
    var obj = { 
     x : sz, 
     y : new Array(sz), 
    }; 

    var _x = obj.x; 

    return function() { 
     return obj.x; 
    }; 
})(1000000); 

怎樣的obj多少是應該保留所產生的閉合?將所有obj都保存在內存中,還是隻有obj.x

我應該說我嘗試過(像新手一樣)在Google Chrome中使用堆分析器。在關閉之前,總堆大小爲5.3MB。關閉後,當我將obj.y數組大小(sz)設置爲1,000,000時,總堆大小爲13.2MB,f保留8MB。這表明obj.y仍然在內存中。當我將sz更改爲10,000,000時,堆大小爲81.9MB,並且f保留了80MB。與剩餘的obj.y一致。但是當我使用100,000,000的sz時,配置文件顯示堆大小隻有5.6M,而f保留0.5MB。這告訴我,obj.y被帶出垃圾。並且在任何時候,f()都會返回正確的值,因此推測可能是閉包按預期工作。

所以問題仍然存在,上述關閉的內存是什麼?顯然,我知道它可能是什麼,但它是什麼?

+2

有一點需要注意,'new Array(n)'不會佔用太多的內存,因爲數組是用「空槽」創建的 - 嘗試'new Array(sz).fill('')'到看到區別 –

+1

Afaik,閉包的垃圾回收是[完成每個變量](http://stackoverflow.com/questions/5326300/garbage-collection-with-node-js),但不是每個對象的屬性。它需要對該對象的使用進行大量的假設。 – Bergi

回答

2

我想你可以告訴我們,如果完整的對象是通過把一個斷點在調試器就行了return obj.x;,然後添加一行來執行用f所擁有的功能來觸發它包括在封閉:

f();

在該斷點處,您可以查詢對象obj,並且您會看到它確實是整個對象。所以我會說,是的,所有的obj都是在封閉的基礎上。

我使用節點並使用Chrome瀏覽器測試了此結果。也許其他的JavaScript引擎可以優化這一點並且行爲有所不同

關於垃圾收集,我會說測量垃圾收集器做什麼是具有挑戰性的事情,因爲當發生這種情況是相當不可預測的,並取決於很多因素。

編輯 - 附加信息

我想提供什麼是怎麼回事與關閉更清晰。在JavaScript中,垃圾收集只會發生在無法訪問的東西(變量,函數等)上。只要有東西可到達,它就不會被垃圾收集。

要查看此功能可以使用的閉包,我們可以在控制檯中使用console.dir()命令。

下面是一個示例控制檯會話(Chrome瀏覽器控制檯):

> var f = (function(sz){ 
    var obj = { 
     x : sz, 
     y : new Array(sz), 
    }; 

    var _x = obj.x; 

    return function() { 
     return obj.x; 
    }; 
    })(1000000); 
<- undefined 
> console.dir(f) 
    function anonymous() 
    arguments: null 
    caller: null 
    length: 0 
    name: "" 
    prototype: Object 
    __proto__:() 
    [[FunctionLocation]]: VM24461:9 
    [[Scopes]]: Scopes[2] 
     0: Closure 
     obj: Object 
      x: 1000000 
      y: Array[1000000] 
     __proto__: Object 
     1: Global 
<- undefined 

現在,是[[Scopes]]我們看到關閉此功能下什麼是利益在這裏,並在閉包是obj。這意味着obj可以訪問,所以不能被垃圾收集。這也意味着obj。y是可達的(通過obj),所以不能被垃圾收集。

希望這有助於提供進一步的清晰度。 console.dir()非常方便查看更多關閉。

+0

我認爲你是對的。如果嘗試調試器(也像一個新手),並觀察相同。但是當我用'return _x'替換時,'obj'不再可觀察。 – codechimp