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

WeakMap.prototype.getOrInsertComputed()

Methode

Gibt den Wert zu <code>key</code> zurück. Fehlt der Schlüssel, wird der Wert mit <code>callbackFn(key)</code> berechnet, in der WeakMap gespeichert und zurückgegeben.

seit JavaScript ECMAScript 2026 (TC39-Proposal „Upsert“); neu, noc Kategorie: method-property

Signatur

WeakMap.prototype.getOrInsertComputed(key, callbackFn)

Beschreibung

Mit getOrInsertComputed() liest du einen Wert aus einer WeakMap und legst ihn in einem Schritt an, falls er noch fehlt. Ist key schon vorhanden, gibst du den gespeicherten Wert zurück, und die Callback-Funktion wird nicht aufgerufen. Fehlt der Schlüssel, wird callbackFn(key) aufgerufen. Das Ergebnis wird unter key gespeichert und zurückgegeben.

Die Methode ersetzt das bekannte Muster if (!wm.has(k)) wm.set(k, berechne()); return wm.get(k);. Sie ist kürzer und schlägt nur einmal nach, wenn der Schlüssel schon existiert. Typische Einsatzfälle sind Caches und Memoisierung pro Objekt und das Speichern privater Metadaten zu DOM-Elementen oder Klasseninstanzen. Dabei soll der Speicher automatisch freigegeben werden, sobald das Schlüsselobjekt nicht mehr erreichbar ist.

Im Unterschied zu getOrInsert() wird der Standardwert nur bei Bedarf berechnet. Das lohnt sich, wenn die Berechnung teuer ist oder Nebenwirkungen hat, zum Beispiel ein neues Objekt anlegen, rechnen oder messen.

Wie bei allen WeakMap-Operationen muss key ein Objekt oder ein nicht registriertes Symbol sein. Primitive Werte sind als Schlüssel nicht erlaubt.

Parameter

Name Typ Default Beschreibung
$key Pflicht object | symbol Der Schlüssel, zu dem der Wert gesucht wird. Erlaubt sind nur Objekte und Symbole, die nicht mit Symbol.for() registriert wurden.
$callbackFn Pflicht (key: object | symbol) => any Funktion, die den Wert berechnet, falls key fehlt. Sie bekommt key als einziges Argument. Ihr Rückgabewert wird gespeichert und zurückgegeben.

Rückgabewert

Typ
any
Beschreibung
Den schon gespeicherten Wert zu key. Fehlt der Schlüssel, den gerade von callbackFn berechneten und eingefügten Wert.

Beispiele

Grundprinzip: Wert nur bei Bedarf berechnen

const wm = new WeakMap();
const user = { name: 'Ada' };

const first = wm.getOrInsertComputed(user, (key) => {
  console.log('berechne für', key.name);
  return { visits: 0 };
});

// Zweiter Aufruf: Callback läuft nicht mehr
const second = wm.getOrInsertComputed(user, () => {
  console.log('wird nie ausgegeben');
  return { visits: 99 };
});

console.log(first === second, second.visits);
berechne für Ada true 0

Teure Berechnung pro Objekt zwischenspeichern

const statsCache = new WeakMap();

const getStats = (numbers) =>
  statsCache.getOrInsertComputed(numbers, (arr) => {
    const sum = arr.reduce((a, b) => a + b, 0);
    return { sum, avg: sum / arr.length, max: Math.max(...arr) };
  });

const messwerte = [3, 8, 1, 12, 6];
console.log(getStats(messwerte));
console.log(getStats(messwerte) === getStats(messwerte)); // aus dem Cache
{ sum: 30, avg: 6, max: 12 } true

Metadaten zu DOM-Elementen ohne Speicherleck

const clickCounts = new WeakMap();

document.addEventListener('click', (event) => {
  const el = event.target;
  const meta = clickCounts.getOrInsertComputed(el, () => ({
    count: 0,
    firstClick: Date.now(),
  }));
  meta.count++;
  console.log(`${el.tagName}: ${meta.count} Klick(s)`);
});
// Wird ein Element aus dem DOM entfernt und ist sonst nicht mehr
// erreichbar, kann der Garbage Collector auch den Eintrag freigeben.
BUTTON: 1 Klick(s) BUTTON: 2 Klick(s)

Vorher/nachher: Ersatz für has/get/set

const listeners = new WeakMap();
const target = {};

// Klassisch:
// if (!listeners.has(target)) listeners.set(target, new Set());
// listeners.get(target).add(handler);

// Mit getOrInsertComputed:
const handler = () => console.log('Event!');
listeners.getOrInsertComputed(target, () => new Set()).add(handler);
listeners.getOrInsertComputed(target, () => new Set()).add(handler);

console.log(listeners.get(target).size);
1

// Wichtig · Fallstricke

  • Sehr neue API: Die Methode stammt aus dem TC39-Proposal „Upsert“ und wird erst von aktuellen Browserversionen und neuen Laufzeitumgebungen unterstützt. Prüfe die Unterstützung vor dem Einsatz, zum Beispiel mit typeof WeakMap.prototype.getOrInsertComputed === 'function'. Alternativ nutzt du ein Polyfill wie core-js.
  • Ungültige Schlüssel: Ist key ein primitiver Wert oder ein mit Symbol.for() registriertes Symbol, wird ein TypeError ausgelöst. Das geschieht noch bevor callbackFn aufgerufen wird. Ein TypeError folgt auch, wenn callbackFn keine Funktion ist.
  • Ausnahmen im Callback: Wirft callbackFn einen Fehler, wird nichts eingefügt, und der Fehler wird weitergereicht.
  • Änderungen im Callback: Setzt der Callback selbst einen Wert für denselben key, wird dieser Wert danach vom Rückgabewert des Callbacks überschrieben. Solche Nebenwirkungen solltest du vermeiden.
  • Kein Unterschied zwischen undefined und fehlend: Gibt der Callback undefined zurück, wird undefined gespeichert. Bei späteren Aufrufen gilt der Schlüssel dann als vorhanden.
  • Ist der Standardwert billig und hat keine Nebenwirkungen, genügt getOrInsert(key, value).