Signatur
Beschreibung
getOrInsert() fasst ein häufiges Muster in einem Aufruf zusammen: „Gibt es schon einen Eintrag für diesen Schlüssel? Wenn ja, gib ihn zurück, sonst lege ihn mit einem Standardwert an.“ Bisher schrieb man dafür has(), set() und get() nacheinander. So musste der Schlüssel mehrfach nachgeschlagen werden, und es entstand leicht umständlicher Code.
Die Methode eignet sich besonders für Metadaten zu Objekten, die mit dem Objekt verschwinden sollen. Beispiele sind Zähler pro DOM-Element, Zwischenspeicher pro Anfrageobjekt oder private Zustände pro Klasseninstanz. Weil WeakMap ihre Schlüssel nur schwach hält, kann die Speicherbereinigung Einträge freigeben, sobald das Schlüsselobjekt nirgends mehr erreichbar ist.
Wichtig: defaultValue wird immer ausgewertet, bevor die Methode läuft, also auch dann, wenn der Schlüssel schon existiert. Ist der Standardwert teuer zu erzeugen (etwa ein großes Objekt oder eine aufwendige Berechnung), nimm besser getOrInsertComputed(). Dort wird die Rückruffunktion nur bei Bedarf aufgerufen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $key Pflicht | object | symbol | Der Schlüssel, nach dem gesucht wird. Erlaubt sind Objekte und nicht registrierte Symbole. Primitive Werte und über Symbol.for() registrierte Symbole lösen einen TypeError aus. |
|
| $defaultValue Pflicht | any | Der Wert, der eingefügt und zurückgegeben wird, wenn es noch keinen Eintrag für key gibt. Er wird bei jedem Aufruf ausgewertet. |
Rückgabewert
key. Fehlte der Schlüssel, ist es defaultValue, das jetzt in der WeakMap gespeichert ist.Beispiele
Grundlagen: vorhandener und fehlender Schlüssel
const wm = new WeakMap();
const a = {};
const b = {};
wm.set(a, 'bereits da');
console.log(wm.getOrInsert(a, 'neu')); // vorhandener Wert bleibt
console.log(wm.getOrInsert(b, 'neu')); // wird eingefügt
console.log(wm.get(b));
Klicks pro DOM-Element zählen
const clickCounts = new WeakMap();
document.addEventListener('click', (event) => {
const el = event.target;
const count = clickCounts.getOrInsert(el, 0) + 1;
clickCounts.set(el, count);
console.log(`${el.tagName} wurde ${count}× geklickt`);
});
// Wird ein Element aus dem DOM entfernt und nicht mehr referenziert,
// kann auch sein Zähler freigegeben werden.
Listener-Listen pro Objekt gruppieren
const listeners = new WeakMap();
const on = (target, fn) => {
// Array nur beim ersten Mal anlegen, danach wiederverwenden
listeners.getOrInsert(target, []).push(fn);
};
const emit = (target, payload) => {
for (const fn of listeners.get(target) ?? []) fn(payload);
};
const user = { name: 'Ada' };
on(user, (p) => console.log('A:', p));
on(user, (p) => console.log('B:', p));
emit(user, 'geändert');
Funktionsprüfung mit Fallback
const getOrInsert = (wm, key, value) => {
if (typeof wm.getOrInsert === 'function') {
return wm.getOrInsert(key, value);
}
if (!wm.has(key)) wm.set(key, value);
return wm.get(key);
};
const cache = new WeakMap();
const req = {};
console.log(getOrInsert(cache, req, { hits: 0 }));
// Wichtig · Fallstricke
- Der Standardwert wird immer ausgewertet: In
wm.getOrInsert(obj, [])entsteht bei jedem Aufruf ein neues Array, auch wenn es danach verworfen wird. Für teure Standardwerte nimmgetOrInsertComputed(key, callback). - Ungültige Schlüssel: Mit Primitiven wie
'id'oder42und mit registrierten Symbolen (Symbol.for()) wirft die Methode einenTypeError. Das gilt auch, wenn der Schlüssel eigentlich nur nachgeschlagen werden sollte. - Kein Ersatz für Aktualisierungen: Ein vorhandener Wert wird nie überschrieben. Um einen Wert zu ändern, brauchst du weiterhin
set(). - Kompatibilität: Die Methode stammt aus dem TC39-Vorschlag „Upsert“ (zusammen mit
Map.prototype.getOrInsert()). Bisher gibt es sie nur in neueren Browserversionen, und sie ist noch nicht Baseline. Für ältere Umgebungen brauchst du eine Funktionsprüfung, ein Polyfill (z. B. core-js) oder das klassische Muster aushas()undset(). - Eine
WeakMaplässt sich nicht durchlaufen. Du kannst also nicht nachträglich auflisten, welche Standardwerte schon eingefügt wurden.