假設你有他們的工作是,組件除其他事項外,創造一些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?),情況會有所不同嗎?
這可能都只是我希望的工作,但我只是試圖說服自己,沒有內存可以從這種模式泄漏。
謝謝。
很遺憾,標記jQuery的問題很少。我很自豪能給我一個+1。 –
瀏覽器使用Mark-and-sweep GC(的變體),因此,當我們離開start填充實例的上下文時,它將被標記爲收集,但div將保留在DOM中。 – jasssonpet
@Truth不客氣。 – phtrivier