簡答:是的。不管引用的對象屬性是什麼,任何未被引用的對象都會從內存中完全刪除。
var objA = (function()
{
var objAb = {who:'An object literal in closure scope',globalReference:'None!'};
return {who:'Return value, is an object literal that references a closure object'.
closureObj : objAb};
})();
var objB = {who:'some object',objAb:{who:'object literal, referenced by objB.objAb'}};
var objBAb = objB.objAb;//reference to obj literal, referenced by objB.objAb
var objAb = objA.closureObj;//reference to obj literal, referenced by objA.closureObj, which in turn references the closure object literal
delete objB.objAb;
console.log(objBAb);//<-- the object literal that was declared as a property of objB still exists
delete objAb;//<-- this reference is gone, but the closure obj still exists
console.log(objA.closureObj);//<-- object is there
基本上,對象是無名的實體:
在你的片段,當你開始使用閉包東西是相當簡單的,但MEM-管理可能很麻煩。用於訪問它們的變量是參考文獻,從不,其中有包含實際的對象本身。這在JS空間中漂浮。當你使用delete someVar
時,你所做的只是取消設置該變量的實際值,這是一個內存地址(類型)。
如果JS GC找不到任何引用包含對象的內存中的位置的變量,它將回收該內存。
就這麼簡單。
當應用了此邏輯,以下代碼:
var objA = (function()
{
var closureObj = {iam:'An object literal defined inside a closure scope'};
var functionsAreObjects = function()
{//nameless function object, inside closure scope, too
return closureObj;
};
var resetFunction = function()
{
this.closureReference = functionsAreObjects();//assign return value to this
};
return {iam:'The returned object literal',
closureReference:closureObj,
reset:resetFunction,
getClosureReference:functionsAreObjects};
})();
delete objA.closureReference;//the closure object IS NOT GC'ed
在前面的例子,最後delete語句會避風港足以對GC關閉對象文本。但是,現在objA
有兩個方法(引用函數對象的屬性)。這些方法仍然引用閉合對象,和仍然被objA
引用,因此closureObj
還不能被GC化。所以,這就是事情變得棘手:
delete objA.closureReference;
delete objA.reset;
delete objA.getClosureReference;
我們已經刪除了所有性能可以鏈接回closureObj
,所以按理說,它會被GC'ed,對不對? - 呃,不完全。 Chrome的V8確實解除了內存的分配,但是我聽說過類似的代碼導致了Opera的泄露,而且它還沒有超出可能性的範疇,即IE可能不會擅於回收內存。
而且,我們已經有效地創造了一個吸氣法getClosureReference
,所以在現實生活中,這是非常有可能發生:
//do stuff
delete objA.closureReference;
var objB = objA.getClosureReference();//<-- created new reference to closure object
//do some more stuff
delete objA.reset;
delete objA.getClosureReference;
在這種情況下,closureObj
不能GC」編輯,因爲它仍然在某處被objB
引用。只有當該變量超出範圍時,纔會釋放closureObj
。這不僅是一個非常可靠的參數與全局變量(它們從未超出範圍,因此從未得到過GC),它也表明儘管它們是閉包,但它們需要更多的開銷:讓一個變量超出範圍並不一定意味着內存被釋放:某些閉包可能會暴露對某個對象或引用該對象的函數的引用......
我已經在這個問題上發佈了一個問題a while ago,但它可能解釋了一些事情。
只是爲了好玩,如果你想要一個嵌套閉包的例子(閉包閉包,閉包,傳遞對方和其他對象)try finding out when what can be GC'ed in the following code
你的全局變量objectA和你的屬性refToA引用同一個對象。一旦兩個參考都消失了,兩個參考的對象都將消失。 –