2

オブジェクトの配列にも接続されている HTML 要素を生成するオブジェクトがあり、そのインスタンスが 1 つあるとします。そのため、要素を作成するときに、要素のネストされた部分 (uploadDelete であるクラス) に次のイベント リスナーも割り​​当てます。

ここで、このイベント リスナーは、作成時に割り当てられた i の値を使用して、それを作成したオブジェクトのインスタンスの delete メソッドを呼び出す必要があります。イベントは Window の下にあるため、インスタンスを i 値とともに無名関数に渡す必要がありました。

したがって、これは非常にユニークな機能をイベントに割り当てます。delete メソッドはリスナーを含む要素を破棄するため、最初に削除したいと思います。私が読んだことから、そうでなければリークを引き起こす可能性があります(?)。私も厳密モードを使用しているため、arguments.callee は使用しません。

file.display.getElementsByClassName('uploadDelete')[0].addEventListener('click',
(function(that,i){
    return function() {
        that.delete(i);
    };
})(this,i), false);

私はさまざまなことを試しましたが、リスナーで呼び出される関数内の関数内に匿名関数を持ち始めたとき、ここで質問する必要があると考えました。他のコードを変更することで全体的な問題を解決できるかもしれませんが、これに答えることができればまだ役に立ちます。


これが、Norguardの答えの助けを借りて、私がやったことです。一意性は file というオブジェクトに由来するため、関数を格納するために file の新しいプロパティを作成しました。

file.deleteFunction = (function(that,i){
    return function() {
        that.delete(i);
    };
})(this,i);

file.display.getElementsByClassName('uploadDelete')[0].addEventListener('click',file.deleteFunction, false);

次に呼び出される削除関数は、イベント リスナーを削除します。

4

1 に答える 1

2

これを行うための比較的簡単な方法は、リスナーの追加と削除を担当するオブジェクトをスコープ内に作成することです。これは、シリアルまたは非シリアルの ID を構築し、オブジェクト内のリスナーが何であれ、その ID を返します。要求されたオブジェクト/モジュールへの ID (または匿名関数をそれらに戻す)。

// trivial example
var listeners = {},
    i = 0,


add = function (context, func, closure) {
    var enclosed = (function (closure) {
        return function () { /* ... */; func(); };
    }(closure)),
    index = i;

    context.addEventListener("...", enclosed, false);
    listeners[index] = enclosed;
    i += 1;
    return index;
};

addこれでリスナーが追加されますが、addEventListener に渡す関数もlistenersオブジェクトに格納されます。への参照が必要な場合は、必要に応じiて既にクロージャーに含まれています。

したがって、何かを削除するときは、 に保存されている関数を探すだけですlisteners[i]

何らかの理由で、これらでいっぱいのテーブルを 1 つの場所に保存したくない場合は、 return ステートメントをキャッチし、 return の代わりにireturn 関数を使用することもできます。

// inside of your module
// I'm not usually crazy about `this`, without doing something particular with it,
// but hopefully it illustrates my point
this.cached_func = add(this.el, this.callback.bind(this), this.secret);

さて、すべてを削除するときが来て、リスナーをシャットダウンしたい場合...

remove(this.cached_func);

そうは言っても、あなたが読んだリークはまだ可能ですが、主な原因は IE6/7 (およびそれ以前) でした。
人々が悪いブラウザーから遠ざかるにつれて、これは重要ではなくなります。
実際、IE6 でメモリ ダンプを奨励することは、人々に IE6 を使用しないように促す良い方法にすぎません。

于 2013-03-20T21:41:13.240 に答える