[解決済み] 要素を削除する前に、イベントリスナーを削除する必要がありますか?
2022-11-21 18:35:08
質問
イベントリスナーがバインドされている子要素を持つ親要素がある場合、親をクリアする前にそれらのイベントリスナーを削除する必要がありますか? (例,
parent.innerHTML = '';
) イベント リスナーが DOM から削除されたときに要素からバインドされていない場合、メモリ リークが発生する可能性がありますか?
どのように解決するのですか?
ここで情報を更新しておきます。私はさまざまなブラウザをテストしてきましたが、特に iframe のオンロード イベントで循環的に依存するイベント リスナーのメモリ リークについてです。
使用したコード(jsfiddle はメモリ テストを妨害するので、これをテストするには独自のサーバーを使用します)。
<div>
<label>
<input id="eventListenerCheckbox" type="checkbox" /> Clear event listener when removing iframe
</label>
<div>
<button id="startTestButton">Start Test</button>
</div>
</div>
<div>
<pre id="console"></pre>
</div>
<script>
(function() {
var consoleElement = document.getElementById('console');
window.log = function(text) {
consoleElement.innerHTML = consoleElement.innerHTML + '<br>' + text;
};
}());
(function() {
function attachEvent(element, eventName, callback) {
if (element.attachEvent)
{
element.attachEvent(eventName, callback);
}
else
{
element[eventName] = callback;
}
}
function detachEvent(element, eventName, callback) {
if (element.detachEvent)
{
element.detachEvent(eventName, callback);
}
else
{
element[eventName] = null;
}
}
var eventListenerCheckbox = document.getElementById('eventListenerCheckbox');
var startTestButton = document.getElementById('startTestButton');
var iframe;
var generatedOnLoadEvent;
function createOnLoadFunction(iframe) {
var obj = {
increment: 0,
hugeMemory: new Array(100000).join('0') + (new Date().getTime()),
circularReference: iframe
};
return function() {
// window.log('iframe onload called');
obj.increment += 1;
destroy();
};
}
function create() {
// window.log('create called');
iframe = document.createElement('iframe');
generatedOnLoadEvent = createOnLoadFunction(iframe);
attachEvent(iframe, 'onload', generatedOnLoadEvent);
document.body.appendChild(iframe);
}
function destroy() {
// window.log('destroy called');
if (eventListenerCheckbox.checked)
{
detachEvent(iframe, 'onload', generatedOnLoadEvent)
}
document.body.removeChild(iframe);
iframe = null;
generatedOnLoadEvent = null;
}
function startTest() {
var interval = setInterval(function() {
create();
}, 100);
setTimeout(function() {
clearInterval(interval);
window.log('test complete');
}, 10000);
}
attachEvent(startTestButton, 'onclick', startTest);
}());
</script>
メモリリークがなければ、テスト実行後、使用メモリは1000kb程度かそれ以下に増加します。しかし、メモリリークがある場合、メモリは約16,000kb増加します。イベント リスナーを最初に削除すると、常にメモリ使用量が少なくなります (リークがない)。
結果
- IE6 - メモリ リーク
- IE7 - メモリリーク
- IE8 - メモリリークなし
- IE9 - メモリリークあり(?????)
- IE10 - メモリ リーク (????)
- IE11 - メモリ リークなし
- Edge (20) - メモリリークなし
- Chrome (50) - メモリリークなし
- Firefox (46) - 言いにくいのですが、ひどくリークしていないので、単に非効率的なガベージコレクタではないでしょうか?明白な理由もなく 4MB を追加して終了します。
- Opera (36) - メモリ リークはありません。
- Safari (9) - メモリリークなし
結論 ブリーディング エッジ アプリケーションは、イベント リスナーを削除しなくてもおそらく大丈夫でしょう。しかし、迷惑をかけたとしても、私はそれが良い習慣であると考えます。
関連
-
[解決済み] プライベートバイト、バーチャルバイト、ワーキングセットとは?
-
[解決済み] 動的に生成された要素にイベントバインディングを行うか?
-
[解決済み] Javascriptで配列から空の要素を削除する
-
[解決済み] JavaScript で DOM ノードのすべての子要素を削除する
-
[解決済み] JavaScriptやデバッグでDOMノード上のイベントリスナーを見つけるには?
-
[解決済み] Reactコンポーネント外でのクリックを検出する
-
[解決済み] JavaScript / jQuery のイベントバインディングを Firebug などでデバッグするには?
-
[解決済み] [Solved] DOM Elementが削除された場合、そのリスナーもメモリから削除されるのですか?
-
[解決済み】AngularJS - $destroyは、イベントリスナーを削除しますか?
-
[解決済み] V8 Javascript エンジンのスタンドアロン実行
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 兄弟ノードを選択する方法はありますか?
-
[解決済み] JSXとLoadshを使用して、ある要素をn回繰り返す方法
-
[解決済み] react-routerのハッシュフラグメントからクエリパラメータを取得する
-
[解決済み] Reactメモを使うべきではない場合とは?
-
[解決済み] イテレータでmap()を使用する
-
[解決済み] Promise : then vs then + catch [重複].
-
[解決済み] Javascript の parseInt() で先頭のゼロを削除する。
-
[解決済み] HTML要素にスクロールバーがあるかどうかをチェックする
-
[解決済み] JavaScriptデータフォーマット/プリティプリンタ
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?