ES6 WeakMapの実際の使い道は?
ECMAScript 6 で導入された WeakMap
データ構造の実際の使い方は?
弱いマップのキーは対応する値への強い参照を作るので、弱いマップに挿入された値は、そのキーが生きている限り 決して 消えないことを保証します。
ということのようです。
weakmap.set(key, value);
...は遠回しに言っているに過ぎません。
key.value = value;
具体的にどのようなユースケースがあるのでしょうか?
373
5
ファンダメンタルズ
WeakMap はガベージコレクションに干渉することなく、外部からオブジェクトを拡張する方法を提供します。 オブジェクトを拡張したいけれど、それがシールされているために拡張できないとき、あるいは外部から拡張されたとき、いつでも WeakMap を適用することが可能です。
WeakMap は key が弱いマップ(辞書)です。つまり、key への参照がすべて失われ、値への参照がなくなれば、value はガベージコレクションされる可能性があります。まず、例題でこれを示し、次に少し説明し、最後に実際の使用例を示して終了しましょう。
例えば、あるAPIを使って、あるオブジェクトを取得するとします。
さて、そのオブジェクトを利用するメソッドがあります。
このメソッドが特定のオブジェクトで何回呼び出されたかを記録し、それがN回以上発生した場合に報告したいのです。素直に考えれば、Map.Dataを使えばいいと思うだろう。
これは動作しますが、メモリリークが発生します。関数に渡されたライブラリオブジェクトの一つ一つを追跡することになり、ライブラリオブジェクトがガベージコレクションされるのを防いでしまうからです。その代わりに、
WeakMap
を使用することができます。そして、メモリリークは解消されます。
使用例
WeakMap`s によって可能になる、他の方法ではメモリーリークが発生するいくつかのユースケースを紹介します。
Let's look at a real use
外部からオブジェクトを拡張するために使用することができます。Node.jsの現実の世界から、実用的な(脚色された、ある種の現実的な-主張をするための)例を挙げましょう。
例えば、あなたがNode.jsで
Promise
オブジェクトを持っているとします。ここで、あなたは現在拒否されているすべてのプロミスを追跡したいのですが、それらへの参照が存在しない場合にガベージコレクションされないようにしたいのです。今、あなたは明白な理由のためにネイティブオブジェクトにプロパティを追加したいとは思っていません。もし、プロミスへの参照を保持するならば、ガベージコレクションが起こらないので、メモリリークを引き起こしていることになります。もしあなたが参照を保持しないなら、あなたは個々のプロミスについての追加情報を保存することができません。プロミスのIDを保存することを含むすべてのスキームは、本質的にあなたがそれへの参照を必要とすることを意味します。
WeakMapsの入力
WeakMapはkeysが弱いことを意味します。弱いマップを列挙したり、そのすべての値を取得する方法はありません。弱いマップでは、キーに基づいてデータを保存し、キーがガベージコレクションされたときに、値もガベージコレクションされます。
つまり、プロミスがあればそれに関する状態を保存でき、そのオブジェクトはまだガベージコレクションされる可能性があります。後でオブジェクトへの参照を得た場合、それに関連する状態があるかどうかを確認し、それを報告することができます。
これは Petka Antonov による unhandled rejection hooks を this として実装するために使われました。
約束に関する情報をマップに保存し、拒否された約束がいつ処理されたかを知ることができます。
この回答は偏った内容で、実戦では使えないと思われます。このまま読んで、実験以外の実際の選択肢としては考えないでください。
ユースケースとしては、リスナー用の辞書として使用することが考えられます、私の同僚でそうしている人がいます。この方法だとどんなリスナーも直接対象になるので、とても便利です。さようなら
listener.on
.しかし、より抽象的な視点から見ると、
WeakMap
は基本的にあらゆるものへのアクセスを非物質化するために特に強力なもので、この構造の性質によってすでに暗示されているので、メンバーを分離するための名前空間は必要ありません。冗長なオブジェクトのキーを置き換えることで、メモリを大幅に改善することができると思います(分解すれば可能ですが)。次を読む前に
Benjamin Gruenbaum]1 が指摘したように (彼の答えが私の答えの上になければ、それを見てください :p) 、この問題は通常の
Map
では解決できなかったでしょう、それはリークしてしまうからです。以下は私の同僚の実際のコードです (共有してくれた 彼 に感謝します)。
フルソースはこちら、上で話したリスナー管理についてです(仕様も見てみてください)。
WeakMap` はカプセル化と情報隠蔽のためにうまく機能する
WeakMap
は ES6 以降で利用可能である。WeakMap
はキーと値のペアのコレクションであり、キーはオブジェクトでなければならない。次の例では、2 つの項目からなるWeakMap
を作成する。set()
メソッドを用いて、オブジェクトと他の項目(この例では文字列)の関連付けを定義しています。オブジェクトに関連付けられたアイテムを取得するために
get()メソッドを使いました。WeakMap
s の興味深い点は、マップ内のキーへの弱い参照を保持していることです。弱い参照ということは、オブジェクトが破棄されると、ガベージコレクタがWeakMap
からエントリ全体を削除するので、メモリが解放されることになります。私は、不変のオブジェクトをパラメーターとして取り込む関数の心配のないメモ作成のキャッシュに「WeakMap」を使用します。
記憶は、「値を計算した後、キャッシュして、再度計算する必要がないようにする」という派手な言い方です。
次に例を示します。
。
。
注意すべきいくつかのこと:
𝗠𝗲𝘁𝗮𝗱𝗮𝘁𝗮。
弱いマップを使用して、ガベージコレクションを妨害したり、同僚をコードで怒らせたりすることなく、DOM要素に関するメタデータを保存できます。 たとえば、それらを使用して、Webページのすべての要素を数値で表示できます。
𝗪𝗶𝘁𝗵𝗼𝘂𝘁 𝗪#120306;𝗮 x
。
。
𝗨𝘀𝗶𝗻𝗴 𝗪𝗲𝗮𝗸𝗠 x
。
。
𝗧𝗵𝗲 𝗗𝗶𝗳𝗳𝗲𝗿𝗯 x
弱者マップのバージョンが長いという事実は別として、違いは無視できるように見えるかもしれませんが、上記の2つのコード間に大きな違いがあります。 コードの最初のスニペットでは、弱いマップなしで、コードの一部はDOM要素間のあらゆる方法を参照します。 これにより、DOM要素がゴミ収集されるのを防ぎます。
Math.po w(i、2)%len]
は、誰も使用しない奇妙なボールのように見えるかもしれませんが、もう一度考えてください。多くのプロダクションコードには、ドキュメント全体で跳ね返るDOM参照があります。 次に、2番目のコードでは、要素へのすべての参照が弱いため、ノードを削除すると、ブラウザはノードが使用されていない(コードで到達できない)と判断できます。したがって、メモリから削除します。 メモリの使用について心配する必要がある理由。, そしてメモリアンカー。 (未使用の要素がメモリに保持されるコードの最初のスニペットなど。) メモリの使用が増えると、ブラウザのGC試行が増えるからです。 (ブラウザのクラッシュを回避するためにメモリを解放しようとします。) ブラウジングエクスペリエンスが遅くなり、ブラウザがクラッシュする場合があります。これらのポリフィルについては、自分のライブラリをお勧めします(ここ@ githubにあります)。 これは非常に軽量なライブラリであり、他のポリフィルにあるような過度に複雑なフレームワークなしで単純にポリフィルします。
。
〜幸せなコーディング。!