イベントリスナーがバインドされている子を持つ親要素がある場合、親をクリアする前にそれらのイベントリスナーを削除する必要がありますか?(つまりparent.innerHTML = '';
)要素がDOMから削除された場合に、イベントリスナーが要素からバインド解除されていない場合、メモリリークが発生する可能性がありますか?
イベントリスナーがバインドされている子を持つ親要素がある場合、親をクリアする前にそれらのイベントリスナーを削除する必要がありますか?(つまりparent.innerHTML = '';
)要素がDOMから削除された場合に、イベントリスナーが要素からバインド解除されていない場合、メモリリークが発生する可能性がありますか?
回答:
短い答え:はい
長い答え:ほとんどのブラウザはこれを正しく処理し、それらのハンドラー自体を削除します。これを台無しにしているいくつかの古いブラウザ(私が正しく思い出せばIE 6と7)があります。はい、メモリリークが発生する可能性があります。これについて心配する必要はありませんが、心配する必要があります。このドキュメントをご覧ください。
IE < 10
現時点ではYahooとAOL以外のサイトにアクセスする人は、安全に非推奨と見なされ、使用されないと思います。とにかく、この時点で皮肉なことにIEを使用している人は、イベントハンドラーがブラウザーのカニを遅くする問題よりも、インドの電話詐欺の被害に遭ったり、ウイルスに感染したりする可能性が高くなります。
ここで情報を更新するだけです。私はさまざまなブラウザをテストしてきました。特に、iframeのonloadイベントで循環的に依存するイベントリスナーのメモリリークについてテストしています。
使用されるコード(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増加します。最初にイベントリスナーを削除すると、常にメモリ使用量が少なくなります(リークはありません)。
結果:
結論:最先端のアプリケーションは、イベントリスナーを削除しないことでおそらく回避できます。しかし、煩わしさにもかかわらず、それでも良い習慣だと思います。