[解決済み】ES6 WeakMapの実際の使い道は?
質問
の実際の使い方はどのようなものですか?
WeakMap
データ構造は ECMAScript 6 で導入されたものですか?
弱いマップのキーは対応する値への強い参照を作成するので、弱いマップに挿入された値が確実に 決して は、そのキーが生きている限り消滅するので、メモ帳やキャッシュなど、通常弱参照や弱値を持つマップなどを使用することはできません。
と思われるのですが、どうでしょう。
weakmap.set(key, value);
...は、遠回しに言っているだけです。
key.value = value;
具体的にどのような使用例があるのでしょうか?
どのように解決するのか?
基本的なこと
WeakMapは、ガベージコレクションに干渉することなく、外部からオブジェクトを拡張する方法を提供します。 あるオブジェクトを拡張したいが、それがシールされているために拡張できない場合、あるいは外部ソースから拡張する場合、いつでも WeakMap を適用することができます。
WeakMapはマップ(辞書)であり、その中に キー へのすべての参照が弱い場合です。 キー が失われ、値への参照もなくなる。 値 はガベージコレクションされる可能性があります。まず例で示し、少し説明し、最後に実際に使ってみましょう。
あるAPIを使って、あるオブジェクトを手に入れたとしよう。
var obj = getObjectFromLibrary();
さて、このオブジェクトを使用するメソッドができました。
function useObj(obj){
doSomethingWith(obj);
}
あるオブジェクトで何回メソッドが呼ばれたかを記録し、それがN回以上発生したら報告したい。素直に考えれば、Mapを使えばいいと思う。
var map = new Map(); // maps can have object keys
function useObj(obj){
doSomethingWith(obj);
var called = map.get(obj) || 0;
called++; // called one more time
if(called > 10) report(); // Report called more than 10 times
map.set(obj, called);
}
これは動作しますが、メモリリークが発生します。関数に渡されたライブラリオブジェクトの一つ一つを追跡することになり、ライブラリオブジェクトがガベージコレクションされるのを防いでしまうからです。その代わりに
WeakMap
:
var map = new WeakMap(); // create a weak map
function useObj(obj){
doSomethingWith(obj);
var called = map.get(obj) || 0;
called++; // called one more time
if(called > 10) report(); // Report called more than 10 times
map.set(obj, called);
}
そして、メモリリークは解消されました。
使用例
そうでなければメモリーリークが発生するようなユースケースで、以下のようなものが有効です。
WeakMap
を含む。
- 特定のオブジェクトに関するプライベートなデータを保持し、マップへの参照を持つ人々だけにアクセスを許可する。よりアドホックなアプローチはprivate-symbolsの提案でやってきますが、それはずっと先の話です。
- ライブラリオブジェクトに関するデータを、変更したりオーバーヘッドを発生させることなく保持することができます。
- 同じ型のオブジェクトが多数存在する場合、JSエンジンが同じ型のオブジェクトに使用する隠しクラスで問題を起こさないように、小さなオブジェクトのセットについてのデータを保持する。
- ブラウザのDOMノードなど、ホストオブジェクトに関するデータを保持する。
- 外部からオブジェクトに能力を追加する(他の回答のイベントエミッターの例のように)。
実際の使用例を見てみましょう
外部からオブジェクトを拡張するために使用することができます。Node.jsの実世界から実用的な(脚色された、ある種の現実的な-ポイントを押さえた)例を挙げてみましょう。
例えば、あなたがNode.jsで
Promise
オブジェクトを作成します。ここで、現在拒否されているすべてのプロミスを追跡したいとします。
ではない
への参照が存在しない場合にガベージコレクションされないようにしたい。
さて、あなたは はしない。 ネイティブ・オブジェクトにプロパティを追加することは、明白な理由で、あなたは行き詰っています。もしあなたがプロミスへの参照を保持するならば、ガベージコレクションが起こらないので、メモリリークを引き起こすことになります。もしあなたが参照を保持しないなら、あなたは個々の約束についての追加情報を保存することができません。約束のIDを保存することを含むすべてのスキームは、本質的にあなたがそれへの参照を必要とすることを意味します。
WeakMapsの導入
WeakMapとは キー は弱い。弱いマップを列挙したり、そのすべての値を取得する方法はありません。弱いマップでは、キーに基づいてデータを保存することができ、キーがガベージコレクションされると、値もガベージコレクションされます。
つまり、プロミスがあれば、それに関する状態を保存することができ、そのオブジェクトはガベージコレクションされる可能性があるということです。後でオブジェクトへの参照を得た場合、それに関連する状態があるかどうかをチェックし、それを報告することができます。
を実装するために使用されました。 未処理拒絶フック として、ペトカ・アントノフが これ :
process.on('unhandledRejection', function(reason, p) {
console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);
// application specific logging, throwing an error, or other logic here
});
プロミスに関する情報をマップに保存し、拒否されたプロミスがいつ処理されたかを知ることができます。
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み] とは何ですか! (not not)演算子とは何ですか?
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] JavaScriptの変数のスコープとは何ですか?
-
[解決済み] JavaScriptの「new」キーワードとは何ですか?
-
[解決済み] Bowerとnpmの違いは何ですか?
-
[解決済み] モバイル端末の検出にはどのような方法がありますか?
-
[解決済み】JavaScript版sleep()とは?)
-
[解決済み】関数の前のエクスクラメーションマークは何をするのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】React Js: Uncaught (in promise) SyntaxError: 位置 0 の JSON で予期しないトークン < が発生しました。
-
[解決済み] [Solved] Uncaught TypeError: nullのプロパティ 'appendChild' を読み取ることができない。
-
[解決済み】React、Uncaught ReferenceError。ReactDOMは定義されていません
-
[解決済み】Javascript - ERR_CONTENT_LENGTH_MISMATCH
-
[解決済み】JavaScript ランタイムエラー:'$'が未定義です。
-
[解決済み】SyntaxError: JSON の位置 1 に予期しないトークン o があります。
-
[解決済み】エラー:リクエストのエンティティが大きすぎる
-
[解決済み】JavaScriptで相対URLへのリダイレクトを行う
-
[解決済み】ES6マップオブジェクトをソートすることは可能ですか?
-
[解決済み] WeakHashMapとWeakReferenceはどんな時に使うのですか?