2012-10-17 49 views
1

據我所知,JS垃圾回收器刪除不再引用的對象。假設我刪除了一個對象的引用,並且該對象有一個屬性,該屬性是對另一個對象的引用。這兩個對象是否會被刪除?垃圾回收器:刪除對一個引用另一個對象的對象的引用

e.g

var objectA = { 
    prop1: "property", 
    prop2: "property" 
} 

var objectB = { 
    refToA: objectA 
} 

// Remove reference to objectA 
delete objectA; 

// Remove reference to objectB 
delete objectB 

既是對象現在已經完全從內存中刪除?

+0

你的全局變量objectA和你的屬性refToA引用同一個對象。一旦兩個參考都消失了,兩個參考的對象都將消失。 –

回答

2

簡答:是的。不管引用的對象屬性是什麼,任何未被引用的對象都會從內存中完全刪除。

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

相關問題