web-dev-qa-db-ja.com

メモリリークなしでDOM要素を削除する方法は?

私のJavaSriptコードは、LI要素のリストを作成します。リストを更新すると、メモリ使用量が増加し、ダウンすることはありません。 sIEveでテストしたところ、ブラウザーは$.remove()または$.empty jQueryコマンドによって削除されるはずのすべての要素を保持していることがわかります。

メモリリークなしでDOMノードを削除するにはどうすればよいですか?

特定のコードについては my other question をご覧ください。

47
podeig

DOMはすべてのDOMノードを保持します。DOMツリー自体から削除された場合でも、これらのノードを削除する唯一の方法はページの更新を行うことです(リストをiframeに入れた場合、更新はそれほど顕著ではありません)

それ以外の場合、ブラウザのガベージコレクターが強制的に動作するように問題が悪化するのを待つことができます(ここでは数百メガバイトの未使用ノードと通信しています)

ベストプラクティスは、ノードを再利用することです。

編集:これを試してください:

var garbageBin;
window.onload = function ()
    {
    if (typeof(garbageBin) === 'undefined')
        {
        //Here we are creating a 'garbage bin' object to temporarily 
        //store elements that are to be discarded
        garbageBin = document.createElement('div');
        garbageBin.style.display = 'none'; //Make sure it is not displayed
        document.body.appendChild(garbageBin);
        }
    function discardElement(element)
        {
        //The way this works is due to the phenomenon whereby child nodes
        //of an object with it's innerHTML emptied are removed from memory

        //Move the element to the garbage bin element
        garbageBin.appendChild(element);
        //Empty the garbage bin
        garbageBin.innerHTML = "";
        }
    }

コンテキストで使用するには、次のようにします。

discardElement(this);
45
Randy the Dev

これは実際の答えよりも[〜#〜] fyi [〜#〜]ですが、非常に興味深いものです。

W3CからDOMコア仕様(http://www.w3.org/TR/DOM-Level-2-Core/core.html):

Core DOM APIは、一般ユーザーのスクリプト言語と、主にプロのプログラマーが使用するより困難な言語の両方を含む、幅広い言語と互換性があるように設計されています。したがって、DOM APIは、明示的なコンストラクターを提供するが自動ガベージコレクションメカニズムを自動的に提供する(特にJava)を通じて、ユーザーにメモリ管理をまったく公開しない言語バインディングから、さまざまなメモリ管理哲学にわたって動作する必要があります未使用のメモリを、特にプログラマがオブジェクトメモリを明示的に割り当て、使用場所を追跡し、再利用のために明示的に解放する必要がある(特にC/C++)メモリに再利用します。これらのプラットフォーム間で一貫したAPIを確保するために、DOMはメモリ管理の問題にまったく対処せず、代わりにこれらを実装に任せます。 DOM API(ECMAScriptおよびJava用)で定義された明示的な言語バインディングのいずれもメモリ管理メソッドを必要としませんが、他の言語(特にCまたはC++)のDOMバインディングはそのようなサポートを必要とします。これらの拡張機能は、DOM APIをDOMワーキンググループではなく特定の言語に適応させる人の責任となります。

つまり、メモリ管理は、さまざまな言語でのDOM仕様の実装に任されています。 JavaScriptでDOM実装のドキュメントを調べて、メモリからDOMオブジェクトを削除する方法を見つける必要がありますが、これはハックではありません。 (ただし、そのトピックに関するMDCサイトにはほとんど情報がありません。)


jQuery#removeおよびjQuery#emptyに関するメモ:これらのメソッドのどちらからも、DOM Objectsからnodesを削除するか、DOM nodesを削除する以外のことはできませんdocumentから。削除するだけですもちろん、これらのオブジェクトにdocumentにないメモリが割り当てられているわけではありません。

編集:上記の文章は、jQueryが驚くことをすることができず、使用されているブラウザーのDOM実装を回避することができないため、余分です。

13
FK82

イベントリスナーを削除しましたか? メモリリークを引き起こす可能性があります

8
Skilldrick

リークを「後修正」する必要があり、クロージャ、循環参照などを考慮してすべてのコードを書き換えずに行う必要がある場合は、削除する前にダグラス・クロックフォードのパージ方法を使用します。

http://javascript.crockford.com/memory/leak.html

または、次のクロージャ修正の回避策を使用します。

http://laurens.vd.oever.nl/weblog/items2005/closures/

1
Jens