2

編集:さらに調べてみると、Firefoxはこれを行っていないようですが、Chromeは間違いなくそうしています。新しいブラウザの単なるバグだと思います.すべてのイベントで、ChromeでもI/O読み取りが発生しますが、FFでは発生しません。

次のページをブラウザーにロードし (Vista の Chrome と Firefox 3 でテストしました)、マウスを動かすと、常にメモリが増加し、減少することはありません。

これは:

  1. ブラウザからの予期される動作
  2. ブラウザのメモリ リークまたは
  3. 提示されたコードのメモリリーク?

.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>test</title>
</head>
<body>
   <script>
      var createEl = function (i) {
          var el = document.createElement("div");
          var t = document.createTextNode(i.toString());
          el.appendChild(t);
          t=null;
          el.id=i.toString();

          var fn = function (e) {};
          el.addEventListener("mouseover", fn, false);
          //el.onmouseover = fn;
          fn = null;

          try{
            return el;
          }
          finally{
            el=null;
          }
          //return (el = [el]).pop();
        };

        var i,x;
        for (i= 0; i < 100; i++){
          x = createEl(i)
          document.body.appendChild(x);
          x = null;
        }
   </script>
</body>
</html>

(el = [el].pop())と のアイデアtry/finallyは両方ともhereからのものですが、どちらも役に立たないようです-当然のことながら、それらはie6の修正のみを目的としているためです。

また、イベントを追加する addEventListener と onmouseover メソッドを使用して実験しました。メモリの増加を防ぐ唯一の方法は、両方のコード行をコメントアウトすることです。

4

3 に答える 3

2

fn は、コードがなくてもクロージャーです。たとえば、Firebug でデバッグを試み、その関数内にブレークポイントを設定します。クロージャーで定義されたすべての変数 (fn コード + ぶら下がっている変数 = クロージャー) は理論的にはアクセス可能です (ただし、実際にそれらにアクセスする方法はわかりません)。

于 2010-12-17T12:24:40.000 に答える
1

イベントハンドラに関連するメモリリークは、一般的に、エンクロージャに関連しています。つまり、その要素を指す関数をイベントハンドラーにアタッチすると、ブラウザーがガベージコレクションを行うのを防ぐことができます。(ありがたいことに、ほとんどの新しいブラウザは「トリックを学習」し、このシナリオではメモリをリークしなくなりましたが、古いブラウザがたくさん浮かんでいます!)

このようなエンクロージャは次のようになります。

var el = document.createElement("div");
var fnOver = function(e) {
    el.innerHTML = "Mouse over!";
};
var fnOut = function(e) {
    el.innerHTML = "Mouse out.";
};

el.addEventListener("mouseover", fnOver, false);
el.addEventListener("mouseout", fnOut, false);

document.getElementsByTagName("body")[0].appendChild(el);

fnOver参照するためにそれらの囲いの範囲に手をfnOut差し伸べるという事実elは、囲いを作成するものであり(2つ、実際には各関数に1つ)、ブラウザーのリークを引き起こす可能性があります。あなたのコードはこのようなことを何もしないので、エンクロージャーを作成しないので、(正常に動作する)ブラウザーがリークすることはありません。

ベータ版ソフトウェアの厄介なものの1つにすぎないと思います。:-)

于 2009-01-29T15:52:44.730 に答える
1

まあ、これは私がこれ処理する方法ではありません。動作を再現することはできません。そのため、fn関数に含まれるものが原因でメモリに関する問題が発生する可能性が高いということだけを伝えることができます。クロージャーfnは、関数の外側で定義し、createEl関数内で参照するだけでよいため、メモリ内にはそのインスタンスが 1 つしか存在しません。

ただし、イベントバインディングをより適切に処理する必要があります(これはxbrowserセーフではありません-現時点では、jQueryを提案することをためらっています)(el =[el]).pop()。それは達成します。

于 2009-01-29T13:26:08.113 に答える