とりわけ、いくつかのDOMノードを作成することを仕事とするコンポーネントがあるとします(たとえば、jqueryを使用)。
function PageFiller() {
}
PageFiller.prototype.fillPage = function () {
this.dom = $("<div/>", {
"class" : "hello",
text : "Hello world"
});
$("body").append(this.dom);
}
「PageFiller」への参照を保持せずに、別のコンポーネントがこれを使用してDOMを埋めるとします。
function Main() {
}
Main.prototype.start = function () {
var filler = new PageFiller();
filler.fillPage();
};
var main = new Main()
main.start();
その直後に(同じスコープで)誰かが残酷にDOMをクリアするとは思わないでください:
$(".hello").remove();
そのような状況でのメモリレイアウトは何ですか?PageFillerインスタンスでメモリリークが発生しましたか?
PageFillerインスタンスは、もう存在しないDOMの一部を表すjqueryオブジェクトへの参照を保持しているため、どの時点でガベージコレクションが行われるのか(発生した場合)は少しわかりません。または、実際のDOMオブジェクトは通常のJS変数とは異なるヒープに存在することを私が理解しているので、それはDOMとは何の関係もありません(ここで間違っていない限り)。
更新:PageFillerへの参照がMainオブジェクトによって保持されている場合、そのバリエーションは次のようになります。
Main.prototype.start = function () {
this.filler = new PageFiller();
filler.fillPage();
}
この状況では、MainオブジェクトにはPageFillerオブジェクトへの参照があり、PageFillerオブジェクト自体はJQオブジェクトへの参照を保持しています。'remove'の後、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を使用して)要素を削除した場合、動作が異なりますか?
これはおそらくすべて私が望むように機能しますが、私はこのパターンからメモリがリークすることはないことを自分自身に確信させようとしています。
ありがとう。