5

たまに、次のようなことをしていることに気づきます。

var img = new Image();
img.src = 'php/getpic.php?z=' + imid + '&th=0';
img.onload = function(){drawImages(img,contexts,sizes)};

説明

  1. HTML画像要素を作成します。
  2. そのsrc属性を割り当てます
  3. onloadイベントを割り当てます
  4. 1つ以上のCanvasコンテキストをイベントハンドラーに渡します
  5. ロードされた画像をキャンバスに描画します

私がはっきりしていないのは、これです-JavaScriptガベージコレクターはimg要素を破棄するタスクを処理しますか、それとも自分で行う必要がありますか、それともメモリリークが遅くなりますか?

4

2 に答える 2

7

JavaScript と DOM の間で循環参照が作成されるため、 IE 6 および 7 (および非常に古いバージョンの FF) でリークします。IE 6 および 7 は、2 つのワールド間で循環参照を持つオブジェクトをガベージ コレクションできません。これは、別々のガベージ コレクタを使用するためです。

最新のブラウザーは、リークすることなくこれを処理できます。

IE 6 および 7 でのリークを防ぐには、作業が完了したら次のようにしますimg

img.onload = null;

最新のブラウザーのみを気にする場合は、心配する必要はありません。(IE 6 と 7 の市場シェアが最終的に十分に低くなったことをとても嬉しく思います!)


アップデート

割り当てた関数onloadはクロージャを作成します。そのクロージャには への参照が含まれていますimgimgそのクロージャが JScript のメモリに存在する限り、DOM のメモリからガベージ コレクションすることはできません (JScript は JavaScript の IE 実装の名前です)。同様に、関数への参照があるimgため、DOM のメモリに存在する限り、JScript のメモリからクロージャをガベージ コレクションすることはできません。img.onloadこれは循環参照です。言い換えれば、drawImages一度実行されたからといって、それが再び実行されないというわけではありません (JScript エンジンはonloadDOM のドメインである 1 回だけ起動することを認識していません)。

あなたが示したパターンは、IE 6 および 7 でメモリ リークを引き起こすことが知られている古典的なパターンです。(1) DOM ノード、(2) クロージャーを作成するその DOM ノード上のイベント ハンドラー、および (3) で構成されます。 ) クロージャー内のその DOM ノードへの参照。

于 2012-11-20T15:32:24.277 に答える
6

メモリ リークが心配な場合は、Google Chrome の Heap Debuggerを使用することをお勧めします。あなたの場合、特定のパターンがメモリリークを引き起こすかどうかを確認できる簡単なテストを作成しました。

<html>
    <head>
        <script>
            function test() {
                var img = new Image();
                img.src = 'php/getpic.php?z=1&th=0';
                img.onload = function(){ drawImages(img,contexts,sizes); };
            }
        </script>
    </head>
    <body>
        <input type="button" onclick="test()" value="test" />
    </body>
</html>

結果に不要なノイズが含まれないように、テストの前に「テスト」を 1 回押すことをお勧めします (コードの初回実行時にメモリに追加されるものがありますが、これはメモリ リークがあるという意味ではありません)。

ヒープ スナップショットを取得し、テストを押してヒープ スナップショットを取得します。実際の結果が必要な場合は、ビューを "Summary" から"Comparaison"に切り替える必要があります。ビューが空の場合 (私がテストしたときの場合)、ステップ中に何も追加されなかったことを意味します。つまり、メモリ リークがないことを意味します。それ以外の場合は、スナップショット間で追加または削除されたものが表示されます。

注 : この方法は、独自の問題がある古いブラウザーのメモリ リークには役立ちませんが、最近のほとんどのブラウザーでメモリ リークの原因となるものを見つけるための良いステップです。

于 2012-11-20T16:06:54.010 に答える