WeakMap) (fortgeschritten)WeakMaps sind ähnlich wie Maps, mit den folgenden Unterschieden
Die nächsten beiden Abschnitte untersuchen detaillierter, was das bedeutet.
Es ist unmöglich, den Inhalt einer WeakMap zu inspizieren.
Diese Einschränkungen ermöglichen eine Sicherheitseigenschaft. Zitiert von Mark Miller
Die Zuordnung von WeakMap/Schlüssel-Paar-Wert kann nur von jemandem beobachtet oder beeinflusst werden, der sowohl die WeakMap als auch den Schlüssel besitzt. Mit
clear()hätte jemand, der nur die WeakMap besitzt, die Zuordnung von WeakMap und Schlüssel zu Wert beeinflussen können.
Die Schlüssel einer WeakMap werden als schwach gehalten bezeichnet: Normalerweise kann ein Objekt nicht vom Garbage Collector eingesammelt werden, solange ein anderes Objekt darauf verweist. Mit einer WeakMap ist das anders: Wenn ein Objekt ein Schlüssel ist und nicht mehr anderweitig referenziert wird, kann es vom Garbage Collector eingesammelt werden, auch wenn die WeakMap noch existiert. Das führt auch dazu, dass der entsprechende Eintrag entfernt wird (aber es gibt keine Möglichkeit, dies zu beobachten).
Alle Schlüssel von WeakMap müssen Objekte sein. Man erhält einen Fehler, wenn man einen primitiven Wert verwendet.
> const wm = new WeakMap();
> wm.set(123, 'test')
TypeError: Invalid value used as weak map keyMit primitiven Werten als Schlüsseln wären WeakMaps keine Black Boxes mehr. Aber da primitive Werte niemals vom Garbage Collector eingesammelt werden, profitiert man ohnehin nicht von schwach gehaltenen Schlüsseln und kann genauso gut eine normale Map verwenden.
Das ist der Hauptanwendungsfall für WeakMaps: Man kann sie verwenden, um externe Werte an Objekte anzuhängen – zum Beispiel
const wm = new WeakMap();
{
const obj = {};
wm.set(obj, 'attachedValue'); // (A)
}
// (B)In Zeile A hängen wir einen Wert an obj an. In Zeile B kann obj bereits vom Garbage Collector eingesammelt werden, obwohl wm noch existiert. Diese Technik, einen Wert an ein Objekt anzuhängen, ist äquivalent dazu, dass eine Eigenschaft dieses Objekts extern gespeichert wird. Wenn wm eine Eigenschaft wäre, würde der vorherige Code wie folgt aussehen
{
const obj = {};
obj.wm = 'attachedValue';
}Mit WeakMaps kann man zuvor berechnete Ergebnisse mit Objekten verknüpfen, ohne sich um die Speicherverwaltung kümmern zu müssen. Die folgende Funktion countOwnKeys() ist ein Beispiel: sie speichert frühere Ergebnisse im WeakMap cache zwischen.
const cache = new WeakMap();
function countOwnKeys(obj) {
if (cache.has(obj)) {
return [cache.get(obj), 'cached'];
} else {
const count = Object.keys(obj).length;
cache.set(obj, count);
return [count, 'computed'];
}
}Wenn wir diese Funktion mit einem Objekt obj verwenden, sieht man, dass das Ergebnis nur beim ersten Aufruf berechnet wird, während beim zweiten Aufruf ein zwischengespeicherter Wert verwendet wird.
> const obj = { foo: 1, bar: 2};
> countOwnKeys(obj)
[2, 'computed']
> countOwnKeys(obj)
[2, 'cached']Im folgenden Code werden die WeakMaps _counter und _action verwendet, um die Werte von virtuellen Eigenschaften von Instanzen von Countdown zu speichern.
const _counter = new WeakMap();
const _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
dec() {
let counter = _counter.get(this);
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
// The two pseudo-properties are truly private:
assert.deepEqual(
Object.keys(new Countdown()),
[]);So wird Countdown verwendet.
let invoked = false;
const cd = new Countdown(3, () => invoked = true);
cd.dec(); assert.equal(invoked, false);
cd.dec(); assert.equal(invoked, false);
cd.dec(); assert.equal(invoked, true); Übung: WeakMaps für private Daten
exercises/weakmaps/weakmaps_private_data_test.mjs
Der Konstruktor und die vier Methoden von WeakMap funktionieren genauso wie ihre Map-Äquivalente.
new WeakMap<K, V>(entries?: Iterable<[K, V]>) [ES6].delete(key: K) : boolean [ES6].get(key: K) : V [ES6].has(key: K) : boolean [ES6].set(key: K, value: V) : this [ES6] Quiz
Siehe Quiz-App.