Start · Sprachen · JavaScript · Referenz · WeakMap.prototype.getOrInsert()

WeakMap.prototype.getOrInsert()

Methode

Gibt den Wert zu <code>key</code> zurück; fehlt der Schlüssel, wird zuerst <code>defaultValue</code> eingefügt und dann zurückgegeben.

seit JavaScript ES2026 (Vorschlag „Upsert“) – noch nicht Baseline, Kategorie: method-property

Signatur

WeakMap.prototype.getOrInsert(key, defaultValue)

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

Typ
any
Beschreibung
Der vorhandene Wert zu 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));
bereits da neu neu

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.
BUTTON wurde 1× geklickt BUTTON wurde 2× geklickt

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');
A: geändert B: 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 }));
{ 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 nimm getOrInsertComputed(key, callback).
  • Ungültige Schlüssel: Mit Primitiven wie 'id' oder 42 und mit registrierten Symbolen (Symbol.for()) wirft die Methode einen TypeError. 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 aus has() und set().
  • Eine WeakMap lässt sich nicht durchlaufen. Du kannst also nicht nachträglich auflisten, welche Standardwerte schon eingefügt wurden.