6

内部では、JQueryは「UUID」のマップ(それが維持するカウンターjQuery.uuid)を使用して、JavascriptからDOMのタグにプロパティをアタッチするときにブラウザーが抱えるよく知られたメモリリークの問題を回避します。そうする代わりに、JQueryはを使用して$.data(tag, name, value)、uuid(チェックすることで判別できるキーtag[jQuery.expando])からキー設定されたマップにデータを格納します。

非常に便利ですが、データを$.data()1つのグローバルバケットにダンプせずにタグにマッピングしたい場合があります。たとえば、データの長さを確認したり、ループしたりできる、独自の小さなデータバケットが必要です。

不自然な例として、クリックすると4つの状態のいずれかを回転するアイコンがあるとします。1つが状態2の場合、状態2のアイコンの配列に追加します。これを行う最も明白な方法は、タグを配列に追加することです。ただし、そうするとメモリリークが発生します。チェックボックスを呼び出すこともできます$.data()が、それでは目的を完全に達成することはできません。すべてのチェックボックスをループして$.data()、リストにあるチェックボックスとないチェックボックスを確認する必要があります。

タグの抽象化を配列に格納する必要があります。これがjQueryのUUIDです。独自のUUID機能を作成することもできますが、理想的には、コードサイズと品質の両方の理由から、JQueryにすでに組み込まれているUUID機能を利用するだけです。JQueryに、呼び出してUUIDをタグに暗黙的にアタッチするように依頼し、そのUUIDを取得するため$.data(tag, 'irrelevant', 1)にチェックtag[jQuery.expando]し、最後にそれをリストで使用することができます...しかし、それはちょっとしたハックです。本当に理想的なのは、パブリックAPIで以下を公開することです。

$.getUuid(tag):UUIDが存在しない場合は、それをチェックして作成します。理想的には、メソッドが除外され、$.data()渡されたタグのuuidが作成またはフェッチされます。

それで、これがjQueryの独自のメソッドに考慮されない理由はありますか?これは何らかの形で有害ですか?それは決して有用と思われるものではなかったのでしょうか?

私が使用しているjQueryのバージョンで実際にそれを除外したことに注意する必要があり、それは非常に役立ちます。しかし、おそらく、私が使用に当たっていない根本的なリスクがあります。これを実現するプラグインも知っていますが、少し壊れています。同じUUID機能を実行するための2つのコードパスがあると、少し無駄が多く、少しもろくなります。

4

2 に答える 2

4

ここでの明白な答えは、jQueryが内部使用のためにuuidを構築し、それを公に消費可能にすることをわざわざする大きな理由や大きな需要を見ていなかったということだと思います。それは理由が存在しないという意味ではなく、ただそれが取り組むべきもののリストのトップにそれを作るのに十分に重要であるように思われなかったということです。

一意のIDとして使用するために単調に増加するカウンターを実装するのは非常に簡単であり、私はこれを何度も使用しました。そのためにクラスライブラリのサポートが必要だとは感じませんでした。

オブジェクト参照を保持しているためにメモリリークが発生することへの恐れは少し誇張されていると思います。まず、オブジェクトを削除し、オブジェクトへの参照を削除するのを忘れた場合、それはメモリリークにすぎません。これは、ガベージコレクションされた言語の一般的なルールであり、オブジェクトへの参照をどこに保持しているかを「知って」、オブジェクトを解放するときにそれらの参照をクリーンアップする必要があります。

次に、ページごとに同じことを何度も行う場合、またはオブジェクトが非常に大きい場合にのみ、意味のあるメモリリークになります。次のページに移動するとすべてがクリーンアップされるため、そのブラウザページを離れることがなく、同じことを何度も繰り返してオブジェクトを削除しない限り、それが永遠に蓄積されるようなものではありませんが、参照は削除されません。

第三に、jQueryの.data()メカニズムは、DOMオブジェクトを使用するときにこれを解決しようとします。

第4に、不自然な例では、状態2のアイコンの配列が無効または使用されなくなったときにクリーンアップしない限り、これによってメモリリークが発生することはありません。クリーンアップすれば、その配列に直接DOM参照を格納することに問題はありません。配列をクリーンアップしないと、DOM参照の代わりに抽象uuidが含まれている場合でも、配列自体でさえメモリリークになります。抽象参照の使用は、ほとんどの場合必要とされるよりもはるかに多くの作業です。

繰り返しになりますが、リークが発生した場合でも、ページの寿命が長く、オブジェクトの作成と解放を繰り返している場合にのみリークが重要になりますが、参照が時間の経過とともに蓄積されるようにオブジェクトへのすべての参照をクリアしてこれを行うわけではありません。それらが引き起こすメモリリークが意味を持つのに十分です。私は常にJS変数でDOMオブジェクトへの参照を保持しています。DOMオブジェクトが将来解放される可能性があることを知っているので、不要になったときにそれらを無効にするように注意しています。

于 2011-08-11T23:06:26.680 に答える
0

これはjQueryチームに送信され、拒否されました。

ただし、次のように、ガベージコレクションをjQueryに委任するタグのリストを維持できます。

http://jsfiddle.net/b9chris/Un2mH/

重要なコードは次のとおりです。

sets[oldIndex] = sets[oldIndex].not(this);
sets[index] = sets[index].add(this);

これにより、個別のメモリ負荷が発生します。これらのメソッドは、配列にタグを追加するだけでなく、このコレクションの以前の状態のスタックも維持します(.pushStack()は内部で呼び出されます)。ページが多くのユーザーアクションで長持ちする場合、コレクションは際限なく大きくなります。これを防ぐには、オブジェクトをハックしてスタックを削除します。

sets[oldIndex] = sets[oldIndex].not(this);
sets[oldIndex].prevObject = null;
sets[index] = sets[index].add(this);
sets[index].prevObject = null;

いくつかのCPUサイクルの無駄ですが、十分にクリーンです。

于 2013-06-14T00:59:20.233 に答える