これとこの MDNページを見ると、MapsとWeakMapsの唯一の違いはWeakMapsの "サイズ"プロパティがないことです。しかし、これは本当ですか?それらの違いは何ですか?
key
あなたが参照しているため、収集できません。
key
あなたが参照しているため、収集できません。
回答:
経験豊富なJavaScriptプログラマーは、このAPIが4つのAPIメソッドで共有される2つの配列(1つはキー、もう1つは値)を使用してJavaScriptに実装できることに気付くでしょう。このような実装には2つの主要な不便があります。最初の検索はO(n)検索です(nはマップ内のキーの数です)。2つ目はメモリリークの問題です。手動で作成されたマップでは、キーの配列はキーオブジェクトへの参照を保持し、それらがガベージコレクションされるのを防ぎます。ネイティブのWeakMapでは、キーオブジェクトへの参照は「弱く」保持されます。つまり、オブジェクトへの参照が他にない場合でも、ガベージコレクションが妨げられることはありません。
参照が弱いため、WeakMapキーは列挙できません(つまり、キーのリストを提供するメソッドはありません)。もしそうなら、リストはガベージコレクションの状態に依存し、非決定論を導入します。
[そして、それが彼らにもsize
財産がない理由です]
キーのリストが必要な場合は、自分で管理する必要があります。 弱い参照を使用せず、列挙可能な単純なセットとマップの導入を目的としたECMAScript提案もあります。
‐これが「通常の」Map
sになります。MDNで述べた、しかしでない調和の提案、それらも持っているitems
、keys
とvalues
発電方法を、実施Iterator
のインターフェイスを。
new Map().get(x)
平野オブジェクトからプロパティを読み込むと同じルックアップ時間について持っていますか?
キー/値で参照されているオブジェクトが削除されると、どちらも動作が異なります。以下のサンプルコードを見てみましょう:
var map = new Map();
var weakmap = new WeakMap();
(function(){
var a = {x: 12};
var b = {y: 12};
map.set(a, 1);
weakmap.set(b, 2);
})()
上記の生命維持には、私たちが参照できる方法はありませんが実行される{x: 12}
と、{y: 12}
もはやは。ガベージコレクターは先に進み、「WeakMap」からキーbポインターを削除し{y: 12}
、メモリからも削除します。ただし、「マップ」の場合、ガベージコレクターは「マップ」からポインターを削除せず{x: 12}
、メモリからも削除しません。
概要:WeakMapを使用すると、ガベージコレクターはタスクを実行できますが、マップは実行できません。
参照:http : //qnimate.com/difference-between-map-and-weakmap-in-javascript/
map.entries().next().value // [{x:12}, 1]
WeakMap
非プリミティブキーのみを持つことができます(Symbol
キーとしての文字列または数値またはsはなく、配列、オブジェクト、その他のマップなどのみ)。
Map
が、そうではありませんWeakMap
多分次の説明は誰かのためにより明確になるでしょう。
var k1 = {a: 1};
var k2 = {b: 2};
var map = new Map();
var wm = new WeakMap();
map.set(k1, 'k1');
wm.set(k2, 'k2');
k1 = null;
map.forEach(function (val, key) {
console.log(key, val); // k1 {a: 1}
});
k2 = null;
wm.get(k2); // undefined
ご覧のとおりk1
、メモリからキーを削除した後も、マップ内でキーにアクセスできます。同時に、k2
WeakMapのキーを削除すると、wm
参照からも削除されます。
そのため、WeakMapにはforEachのような列挙可能なメソッドがありません。これは、WeakMapキーのリストなどがないため、別のオブジェクトへの参照にすぎません。
forEach
、(key, val)
実際にもしなければならない(val, key)
別の違い(ソース:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap):
WeakMapsのキーは、オブジェクトタイプのみです。キーとしてのプリミティブデータタイプは許可されません(たとえば、シンボルをWeakMapキーにすることはできません)。
文字列、数値、ブール値をWeakMap
キーとして使用することもできません。は、キーにプリミティブ値を使用Map
できます。
w = new WeakMap;
w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key
m = new Map
m.set('a', 'b'); // Works
Javascript.infoから
マップ -通常のマップでキーとしてオブジェクトを使用する場合、マップが存在する間、そのオブジェクトも存在します。メモリを占有し、ガベージコレクションされない可能性があります。
let john = { name: "John" };
let array = [ john ];
john = null; // overwrite the reference
// john is stored inside the array, so it won't be garbage-collected
// we can get it as array[0]
同様に、通常のMapでキーとしてオブジェクトを使用すると、Mapが存在する間、そのオブジェクトも存在します。メモリを占有し、ガベージコレクションされない可能性があります
let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null; // overwrite the reference
// john is stored inside the map,
// we can get it by using map.keys()
WeakMap-オブジェクトのキーとしてオブジェクトを使用し、そのオブジェクトへの他の参照がない場合、メモリ(およびマップ)から自動的に削除されます。
let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // overwrite the reference
// john is removed from memory!
JavaScriptのWeapMapはキーや値を保持せず、一意のIDを使用してキー値を操作し、キーオブジェクトにプロパティを定義します。
key object
メソッドによってプロパティを定義するためObject.definePropert()
、キーはプリミティブ型であってはなりません。
また、WeapMapには実際にはキーと値のペアが含まれていないため、weakmapの長さプロパティを取得できません。
また、操作された値がキーオブジェクトに割り当てられるため、ガベージコレクターは、キーが使用されなくなった場合でも簡単にキーを収集できます。
実装のためのサンプルコード。
if(typeof WeapMap != undefined){
return;
}
(function(){
var WeapMap = function(){
this.__id = '__weakmap__';
}
weakmap.set = function(key,value){
var pVal = key[this.__id];
if(pVal && pVal[0] == key){
pVal[1]=value;
}else{
Object.defineProperty(key, this.__id, {value:[key,value]});
return this;
}
}
window.WeakMap = WeakMap;
})();
実装のリファレンス
id
が、Math.randomやDate.now()などを使用して一意にする必要があります。この動的IDを追加することで、最初の点を解決できます。最後の2つのポイントの解決策を提供していただけませんか。
WeakMap
キーはプリミティブ値ではなくオブジェクトでなければなりません。
let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "ok"); // works fine (object key)
// can't use a string as the key
weakMap.set("test", "Not ok"); // Error, because "test" is not an object
なぜ????
以下の例を見てみましょう。
let user = { name: "User" };
let map = new Map();
map.set(user, "...");
user = null; // overwrite the reference
// 'user' is stored inside the map,
// We can get it by using map.keys()
通常
Map
のでオブジェクトをキーとして使用する場合、Map
が存在する間、そのオブジェクトも存在します。メモリを占有し、ガベージコレクションされない可能性があります。
WeakMap
この点で根本的に異なります。キーオブジェクトのガベージコレクションを妨げません。
let user = { name: "User" };
let weakMap = new WeakMap();
weakMap.set(user, "...");
user = null; // overwrite the reference
// 'user' is removed from memory!
オブジェクトをキーとして使用し、そのオブジェクトへの他の参照がない場合、オブジェクトはメモリ(およびマップ)から自動的に削除されます。
WeakMap
反復とメソッドkeys()、values()、entries()をサポートしていないため、そこからすべてのキーまたは値を取得する方法はありません。
WeakMapには次のメソッドのみがあります。
オブジェクトが他のすべての参照(上記のコードの 'user'など)を失った場合と同様に、オブジェクトは自動的にガベージコレクションされます。しかし、技術的には、クリーンアップがいつ発生するかは正確には指定されていません。
JavaScriptエンジンがそれを決定します。すぐにメモリのクリーンアップを実行するか、削除がさらに発生したときに待機してクリーニングを実行するかを選択できます。したがって、技術的にはaの現在の要素数WeakMap
は不明です。エンジンがそれをクリーンアップしたかどうか、または部分的に実行した可能性があります。そのため、すべてのキー/値にアクセスするメソッドはサポートされていません。
注: -WeakMapのアプリケーションの主な領域は、追加のデータストレージです。オブジェクトがガベージコレクションされるまでオブジェクトをキャッシュするように。