| [ Web Proxy ] |
| Viewing: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/WeakMap | [Back] [Original] |
Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.
Diese Funktion ist gut etabliert und funktioniert auf vielen Gerten und in vielen Browserversionen. Sie ist seit Juli 2015 browserbergreifend verfgbar.
* Einige Teile dieser Funktion werden mglicherweise unterschiedlich gut untersttzt.
Ein WeakMap ist eine Sammlung von Schlssel/Wert-Paaren, deren Schlssel Objekte oder nicht registrierte Symbole sein mssen, mit Werten eines beliebigen JavaScript-Typs, und die keine starken Referenzen auf ihre Schlssel erstellt. Das heit, die Prsenz eines Objekts als Schlssel in einer WeakMap verhindert nicht, dass das Objekt dem Garbage-Collector zum Opfer fllt. Sobald ein Objekt, das als Schlssel verwendet wird, gesammelt wurde, werden seine entsprechenden Werte in jeder WeakMap ebenfalls fr die Mllsammlung in Frage kommen solange sie nicht anderswo stark referenziert werden. Der einzige primitive Typ, der als WeakMap-Schlssel verwendet werden kann, ist das Symbol genauer gesagt nicht registrierte Symbole weil nicht registrierte Symbole garantiert einzigartig sind und nicht neu erstellt werden knnen.
WeakMap ermglicht es, Daten mit Objekten zu assoziieren, ohne zu verhindern, dass die Schlsselobjekte gesammelt werden, selbst wenn die Werte die Schlssel referenzieren. Allerdings erlaubt WeakMap nicht die Beobachtung der Existenz seiner Schlssel, weshalb sie keine Enumeration zulsst; wenn eine WeakMap eine Methode bereitstellen wrde, um eine Liste ihrer Schlssel zu erhalten, wrde die Liste vom Zustand der Mllsammlung abhngen, was zu Nicht-Determinismus fhren wrde. Wenn Sie eine Liste von Schlsseln haben mchten, sollten Sie eine Map anstelle einer WeakMap verwenden.
Sie knnen mehr ber WeakMap im Abschnitt WeakMap-Objekt des Leitfadens zu Schlssel-Sammlungen erfahren.
Schlssel von WeakMaps mssen dem Garbage-Collector ausgeliefert werden knnen. Die meisten primitiven Datentypen knnen willkrlich erstellt werden und haben keine Lebensdauer, daher knnen sie nicht als Schlssel verwendet werden. Objekte und nicht registrierte Symbole knnen als Schlssel verwendet werden, da sie dem Garbage-Collector ausgeliefert werden knnen.
Wie bei regulren Map basiert die Wertegleichheit auf dem SameValueZero-Algorithmus, der dem ===-Operator entspricht, da WeakMap nur Objekt- und Symbolschlssel enthalten kann. Das bedeutet, dass fr Objektschlssel die Gleichheit auf der Objektidentitt basiert. Sie werden durch Referenz und nicht durch Wert verglichen.
Eine Map-API knnte in JavaScript mit zwei Arrays (eines fr Schlssel, eines fr Werte) implementiert werden, die von den vier API-Methoden gemeinsam genutzt werden. Das Setzen von Elementen in dieser Map wrde bedeuten, gleichzeitig einen Schlssel und einen Wert an das Ende jedes der Arrays zu schieben. Dadurch wrden die Indizes des Schlssels und des Werts mit beiden Arrays korrespondieren. Das Abrufen von Werten aus der Map wrde das Durchlaufen aller Schlssel erfordern, um eine bereinstimmung zu finden, und dann den Index dieser bereinstimmung verwenden, um den entsprechenden Wert aus dem Werte-Array abzurufen.
Eine solche Implementierung hat zwei Hauptnachteile:
O(n)-Setzen und Suchen (n ist die Anzahl der Schlssel in der Map), da beide Operationen die Liste der Schlssel durchlaufen mssen, um einen passenden Wert zu finden.Im Gegensatz dazu bezieht sich in einer WeakMap ein Schlsselobjekt stark auf seinen Inhalt, solange der Schlssel nicht dem Garbage-Collector zum Opfer gefallen ist, aber danach schwach darauf. Daher:
WeakMap nicht die Mllsammlung, die letztendlich Referenzen zum Schlsselobjekt entferntWeakMap die Mllsammlung jeglicher Werte, wenn ihre Schlsselobjekte nicht von einem anderen Ort als einer WeakMap referenziert werdenEine WeakMap kann ein besonders ntzliches Konstrukt sein, wenn man Schlssel mit Informationen verknpft, die nur dann wertvoll sind, wenn der Schlssel nicht dem Garbage-Collector zum Opfer gefallen ist.
Aber da eine WeakMap nicht die Beobachtung der Existenz ihrer Schlssel erlaubt, sind ihre Schlssel nicht aufzhlbar. Es gibt keine Methode, um eine Liste der Schlssel zu erhalten. Wenn es eine gbe, wrde die Liste vom Zustand der Mllsammlung abhngen, was zu Nicht-Determinismus fhren wrde. Wenn Sie eine Liste von Schlsseln haben mchten, sollten Sie eine Map verwenden.
WeakMap()Erstellt ein neues WeakMap-Objekt.
Diese Eigenschaften sind auf WeakMap.prototype definiert und werden von allen WeakMap-Instanzen geteilt.
WeakMap.prototype.constructorDie Konstruktorfunktion, die das Instanzobjekt erstellt hat. Fr WeakMap-Instanzen ist der anfngliche Wert der WeakMap-Konstruktor.
WeakMap.prototype[Symbol.toStringTag]Der anfngliche Wert der [Symbol.toStringTag]-Eigenschaft ist der String "WeakMap". Diese Eigenschaft wird in Object.prototype.toString() verwendet.
WeakMap.prototype.delete()Entfernt den durch den Schlssel angegebenen Eintrag aus dieser WeakMap.
WeakMap.prototype.get()Gibt den Wert zurck, der dem Schlssel in dieser WeakMap entspricht, oder undefined, wenn keiner vorhanden ist.
WeakMap.prototype.getOrInsert()Gibt den Wert zurck, der dem angegebenen Schlssel in dieser WeakMap entspricht. Wenn der Schlssel nicht vorhanden ist, wird ein neuer Eintrag mit dem Schlssel und einem angegebenen Standardwert eingefgt und der eingefgte Wert zurckgegeben.
WeakMap.prototype.getOrInsertComputed()Gibt den Wert zurck, der dem angegebenen Schlssel in dieser WeakMap entspricht. Wenn der Schlssel nicht vorhanden ist, wird ein neuer Eintrag mit dem Schlssel und einem Standardwert eingefgt, der aus einem gegebenen Rckruf berechnet wird, und der eingefgte Wert wird zurckgegeben.
WeakMap.prototype.has()Gibt einen booleschen Wert zurck, der angibt, ob ein Eintrag mit dem angegebenen Schlssel in dieser WeakMap existiert oder nicht.
WeakMap.prototype.set()Fgt einen neuen Eintrag mit einem angegebenen Schlssel und Wert zu dieser WeakMap hinzu oder aktualisiert einen bestehenden Eintrag, wenn der Schlssel bereits existiert.
const wm1 = new WeakMap();
const wm2 = new WeakMap();
const wm3 = new WeakMap();
const o1 = {};
const o2 = () => {};
const o3 = window;
wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // a value can be anything, including an object or a function
wm2.set(o2, undefined);
wm2.set(wm1, wm2); // keys and values can be any objects. Even WeakMaps!
wm1.get(o2); // "azerty"
wm2.get(o2); // undefined, because that is the set value
wm2.get(o3); // undefined, because there is no key for o3 on wm2
wm1.has(o2); // true
wm2.has(o2); // true (even if the value itself is 'undefined')
wm2.has(o3); // false
wm3.set(o1, 37);
wm3.get(o1); // 37
wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false
class ClearableWeakMap {
#wm;
constructor(init) {
this.#wm = new WeakMap(init);
}
clear() {
this.#wm = new WeakMap();
}
delete(k) {
return this.#wm.delete(k);
}
get(k) {
return this.#wm.get(k);
}
has(k) {
return this.#wm.has(k);
}
set(k, v) {
this.#wm.set(k, v);
return this;
}
}
Entwickler knnen eine WeakMap verwenden, um private Daten mit einem Objekt zu verknpfen, mit den folgenden Vorteilen:
Map hlt eine WeakMap keine starken Referenzen auf das Objekt, das als Schlssel verwendet wird, sodass die Metadaten die gleiche Lebensdauer wie das Objekt selbst teilen, was Speicherlecks vermeidet.Symbol-Eigenschaften ist eine WeakMap extern zum Objekt und es gibt keine Mglichkeit fr Benutzer-Code, die Metadaten durch reflektive Methoden wie Object.getOwnPropertySymbols abzurufen.let Thing;
{
const privateScope = new WeakMap();
let counter = 0;
Thing = function () {
this.someProperty = "foo";
privateScope.set(this, {
hidden: ++counter,
});
};
Thing.prototype.showPublic = function () {
return this.someProperty;
};
Thing.prototype.showPrivate = function () {
return privateScope.get(this).hidden;
};
}
console.log(typeof privateScope);
// "undefined"
const thing = new Thing();
console.log(thing);
// Thing {someProperty: "foo"}
thing.showPublic();
// "foo"
thing.showPrivate();
// 1
Dies kommt ungefhr dem folgenden gleich, unter Verwendung von privaten Feldern:
class Thing {
static #counter = 0;
#hidden;
constructor() {
this.someProperty = "foo";
this.#hidden = ++Thing.#counter;
}
showPublic() {
return this.someProperty;
}
showPrivate() {
return this.#hidden;
}
}
const thing = new Thing();
console.log(thing);
// Thing {someProperty: "foo"}
thing.showPublic();
// "foo"
thing.showPrivate();
// 1
Eine WeakMap kann verwendet werden, um Metadaten mit einem Objekt zu verknpfen, ohne die Lebensdauer des Objekts selbst zu beeinflussen. Dies ist dem Beispiel der privaten Mitglieder sehr hnlich, da private Mitglieder ebenfalls als externe Metadaten modelliert sind, die nicht an der prototypischen Vererbung teilnehmen.
Dieser Anwendungsfall kann auf bereits erstellte Objekte ausgeweitet werden. Zum Beispiel mchten wir im Web mglicherweise zustzliche Daten mit einem DOM-Element verknpfen, auf das das DOM-Element spter zugreifen kann. Ein gngiger Ansatz ist es, die Daten als Eigenschaft hinzuzufgen:
const buttons = document.querySelectorAll(".button");
buttons.forEach((button) => {
button.clicked = false;
button.addEventListener("click", () => {
button.clicked = true;
const currentButtons = [...document.querySelectorAll(".button")];
if (currentButtons.every((button) => button.clicked)) {
console.log("All buttons have been clicked!");
}
});
});
Dieser Ansatz funktioniert, hat aber ein paar Stolpersteine:
clicked-Eigenschaft ist aufzhlbar, sodass sie in Object.keys(button), for...in-Schleifen usw. angezeigt wird. Dies kann durch die Verwendung von Object.defineProperty() gemildert werden, aber das macht den Code ausfhrlicher.clicked-Eigenschaft ist eine normale String-Eigenschaft, sodass sie von anderem Code zugegriffen und berschrieben werden kann. Dies kann durch die Verwendung eines Symbol-Schlssels gemildert werden, aber der Schlssel wre weiterhin ber Object.getOwnPropertySymbols() zugnglich.Die Verwendung einer WeakMap behebt diese Probleme:
const buttons = document.querySelectorAll(".button");
const clicked = new WeakMap();
buttons.forEach((button) => {
clicked.set(button, false);
button.addEventListener("click", () => {
clicked.set(button, true);
const currentButtons = [...document.querySelectorAll(".button")];
if (currentButtons.every((button) => clicked.get(button))) {
console.log("All buttons have been clicked!");
}
});
});
Hier wei nur der Code, der Zugriff auf clicked hat, den Zustand dieser State und externer Code kann den Zustand nicht modifizieren. Zudem werden, wenn eines der Schaltflchen-Elemente aus dem DOM entfernt wird, die zugehrigen Metadaten automatisch dem Garbage-Collector zum Opfer fallen.
Sie knnen Objekte, die an eine Funktion bergeben werden, mit dem Ergebnis der Funktion verknpfen, sodass wenn dasselbe Objekt erneut bergeben wird, das zwischengespeicherte Ergebnis zurckgegeben werden kann, ohne die Funktion erneut auszufhren. Dies ist ntzlich, wenn die Funktion rein ist (d.h. sie verndert keine auenstehenden Objekte oder verursacht andere beobachtbare Seiteneffekte).
const cache = new WeakMap();
function handleObjectValues(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const result = Object.values(obj).map(heavyComputation);
cache.set(obj, result);
return result;
}
Dies funktioniert nur, wenn die Eingabe Ihrer Funktion ein Objekt ist. Selbst wenn die Eingabe nie erneut bergeben wird, bleibt das Ergebnis fr immer im Cache, solange der Schlssel (Eingabe) existiert. Eine effektivere Methode ist die Verwendung einer Map gepaart mit WeakRef-Objekten, die es ermglichen, jeden Eingabewert mit seinem entsprechenden (potenziell groen) Berechnungsergebnis zu verknpfen. Weitere Details finden Sie im Beispiel WeakRefs und FinalizationRegistry.
| Spezifikation |
|---|
| ECMAScript 2027 LanguageSpecification # sec-weakmap-objects |
WeakMapObject/FunctionDer Bauplan fr ein besseres Internet.
Teile dieses Inhalts sind 19982026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfgbar unter einer Creative-Commons-Lizenz.
| Web Proxy Viewer | New URL | Original Page |