Signatur
Beschreibung
Die Methode getOrInsert() fasst ein sehr häufiges Muster in einem Aufruf zusammen: „Hole den Wert zu einem Schlüssel; gibt es noch keinen, lege einen Standardwert an.“ Existiert key bereits in der Map, wird der vorhandene Wert unverändert zurückgegeben. Andernfalls wird defaultValue unter key gespeichert und dann zurückgegeben.
Bisher schrieb man dafür meist if (!map.has(key)) map.set(key, wert); return map.get(key);. Das braucht bis zu drei Hash-Zugriffe und ist fehleranfällig. getOrInsert() ist kürzer, sagt klarer, was gemeint ist, und kann von der Engine effizienter umgesetzt werden. Typische Einsätze sind Gruppierungen (Schlüssel → Array), Zähler (Schlüssel → Zahl) und verschachtelte Maps.
Wichtig: defaultValue wird immer ausgewertet, bevor die Methode aufgerufen wird, auch wenn der Schlüssel schon existiert. Bei teuren oder seiteneffektbehafteten Standardwerten nimmt man deshalb Map.prototype.getOrInsertComputed(). Dort wird der Wert über eine Callback-Funktion erst bei Bedarf berechnet.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $key Pflicht | any | Der Schlüssel, der gesucht wird. Der Vergleich läuft wie bei Map über SameValueZero (NaN ist gleich NaN, -0 wird zu +0). |
|
| $defaultValue Pflicht | any | Der Wert, der eingefügt und zurückgegeben wird, falls key noch nicht in der Map steht. Er wird bei jedem Aufruf ausgewertet. |
Rückgabewert
key. Fehlte der Schlüssel, ist es der gerade eingefügte defaultValue. Wurde unter dem Schlüssel ausdrücklich undefined gespeichert, kommt undefined zurück, und nichts wird überschrieben.Beispiele
Einfacher Fall: vorhandener und fehlender Schlüssel
const config = new Map([['theme', 'dark']]);
console.log(config.getOrInsert('theme', 'light')); // vorhanden → bleibt
console.log(config.getOrInsert('lang', 'de')); // fehlt → wird eingefügt
console.log([...config]);
Einträge nach Kategorie gruppieren
const produkte = [
{ name: 'Apfel', kategorie: 'Obst' },
{ name: 'Möhre', kategorie: 'Gemüse' },
{ name: 'Birne', kategorie: 'Obst' }
];
const gruppen = new Map();
for (const p of produkte) {
// Beim ersten Treffer ein leeres Array anlegen, danach das vorhandene nutzen
gruppen.getOrInsert(p.kategorie, []).push(p.name);
}
console.log(Object.fromEntries(gruppen));
Wörter zählen
const text = 'das ist das Haus vom Nikolaus das';
const zaehler = new Map();
for (const wort of text.split(' ')) {
zaehler.set(wort, zaehler.getOrInsert(wort, 0) + 1);
}
console.log(zaehler.get('das'));
Fallback für Umgebungen ohne Unterstützung
const getOrInsert = (map, key, defaultValue) => {
if (typeof map.getOrInsert === 'function') {
return map.getOrInsert(key, defaultValue);
}
if (!map.has(key)) map.set(key, defaultValue);
return map.get(key);
};
const cache = new Map();
console.log(getOrInsert(cache, 'user:1', { visits: 0 }));
// Wichtig · Fallstricke
- Kompatibilität: Die Methode stammt aus dem TC39-Proposal „Upsert“ (Stage 3) und ist erst in neueren Browser- und Engine-Versionen verfügbar. Für Produktivcode braucht man Feature-Erkennung (
typeof Map.prototype.getOrInsert === 'function') oder ein Polyfill, etwa aus core-js. - Eifrige Auswertung:
map.getOrInsert(k, [])erzeugt bei jedem Aufruf ein neues Array, auch wenn es verworfen wird. Bei teuren Standardwerten (Objekte mit großem Aufbau, Netzwerk- oder DOM-Zugriffe) istgetOrInsertComputed(key, callback)die bessere Wahl. - Keine Überschreibung: Anders als bei
map.get(k) ?? defaultValuewird ein ausdrücklich gespeicherter Wert wieundefinedodernullnicht ersetzt. Maßgeblich ist nur, ob der Schlüssel existiert. - Objekt-Schlüssel werden über ihre Identität verglichen:
getOrInsert({}, 1)legt jedes Mal einen neuen Eintrag an. - Die gleiche Methode gibt es auch als
WeakMap.prototype.getOrInsert(). Dort sind nur Objekte (und nicht registrierte Symbole) als Schlüssel erlaubt.