2012-05-30 118 views
5

假設你有他們的工作是,組件除其他事項外,創造一些DOM節點(使用jQuery如):避免內存泄漏

function PageFiller() { 
} 
PageFiller.prototype.fillPage = function() { 
    this.dom = $("<div/>", { 
    "class" : "hello", 
    text : "Hello world" 
    }); 
    $("body").append(this.dom); 
} 

假設另一個組件使用此填補了DOM,沒有保持一個參考「PageFiller」

function Main() { 
} 
Main.prototype.start = function() { 
    var filler = new PageFiller(); 
    filler.fillPage(); 
}; 
var main = new Main() 
main.start(); 

沒有假設後正確的(在相同的範圍內),有人慘遭清除DOM:

$(".hello").remove(); 

這種情況下的內存佈局是什麼?我是否使用PageFiller實例泄漏了內存?

我有點不確定在哪一點PageFiller實例會得到垃圾回收(如果它曾經發生過),因爲它持有對jquery對象的引用,表示不再存在的DOM的一部分? 或者它什麼都沒有做與DOM,因爲從我瞭解的實際DOM對象生活在一個不同的堆比普通JS變量(除非是我弄錯了這裏..)

更新:一個變化的事情是,如果到PageFiller參考保持各主要對象:

Main.prototype.start = function() { 
    this.filler = new PageFiller(); 
    filler.fillPage(); 
} 

在這種情況下,主要對象涉及到PageFiller對象,其本身持有的JQ對象的引用的參考; '刪除'後,JQ對象仍然存在於內存中,但指向不存在的DOM節點,對吧?

我是正確地說,在最初的例子,只要main.start()完成:

  • 沒有對象保存到PageFiller對象的引用,所以它被垃圾回收,和pageFiller.dom對象沒有被任何人引用,所以它也被垃圾收集?
  • 實際的DOM元素顯然還是存在於內存中,但在一個單獨堆中我真的不擔心

另一種情況:

這一次小的變化,與事件處理程序使問題複雜化:

PageFiller.prototype.fillPage = function() { 
    var self = this; 
    this.dom = ... // as usual 
    this.dom.click(function() { 
    alert("Just clicked on dom generated by " + self); 
    }); 
} 

這一次,只是讓PageFiller實例運行的範圍不能足有它的內存回收,因爲它是通過單擊處理程序使用的封閉引用。我在這裏泄漏了記憶嗎?或者我可以信任$(「」)。remove()調用來終止對閉包的引用,因此會終止對PageFiller的最後一個引用?如果我刪除沒有jQuery的元素(使用本地DOM API?),情況會有所不同嗎?

這可能都只是我希望的工作,但我只是試圖說服自己,沒有內存可以從這種模式泄漏。

謝謝。

+0

很遺憾,標記jQuery的問題很少。我很自豪能給我一個+1。 –

+0

瀏覽器使用Mark-and-sweep GC(的變體),因此,當我們離開start填充實例的上下文時,它將被標記爲收集,但div將保留在DOM中。 – jasssonpet

+0

@Truth不客氣。 – phtrivier

回答

1

更新

卸下filler.dom一旦main.start()完成將減少引用計數爲它的舉行對節點,因爲它不擁有的節點(即微弱的屬性)。

當您調用$().remove()時,實際節點被刪除時,refcount再次減少到零並且可以被垃圾收集。

所以,AFAICT你應該沒有什麼可擔心的。

+0

那麼誰在這種情況下擁有節點呢?有沒有一種方法可以訪問refcounts(使用Firebug或Chrome開發工具?)另外我更新了一些其他案例的問題,只是爲了確保。 – phtrivier

+0

@phtrivier當'filler'被標記爲GC時,只有DOM「擁有」該節點。不幸的是,你不可能親自看到引用數;另請參閱:http://stackoverflow.com/questions/2937120/how-to-get-javascript-object-references-or-reference-count –