Signatur
Beschreibung
Object.groupBy() läuft über ein beliebiges iterierbares Objekt, zum Beispiel ein Array, ein Set, einen String oder einen Generator. Für jedes Element ruft die Methode die Callback-Funktion auf. Der Rückgabewert wird in einen Eigenschaftsschlüssel umgewandelt, also einen String oder ein Symbol. Unter diesem Schlüssel landet das Element in einem Array. Das Ergebnis ist ein Objekt, in dem jede Gruppe als eigene Eigenschaft liegt.
Die Methode ersetzt das bekannte Muster mit reduce() und Akkumulator-Objekt, etwa beim Gruppieren von Bestellungen nach Status, Nutzern nach Rolle oder Log-Einträgen nach Level. Die Elemente werden nicht kopiert. Die Gruppen enthalten dieselben Referenzen wie die Quelle.
Das zurückgegebene Objekt hat den Prototyp null. Es erbt also keine Methoden wie hasOwnProperty oder toString. Dadurch gibt es keine Konflikte mit Schlüsseln wie "constructor" oder "__proto__". Sollen die Schlüssel keine Strings sein (z. B. Objekte), nimmt man Map.groupBy().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $items Pflicht | Iterable<T> | Das iterierbare Objekt, dessen Elemente gruppiert werden, z. B. ein Array, Set, String oder Generator. |
|
| $callbackFn Pflicht | (element: T, index: number) => string | symbol | any | Wird für jedes Element aufgerufen und erhält das aktuelle element und seinen index. Der Rückgabewert wird in einen Eigenschaftsschlüssel (String oder Symbol) umgewandelt und bestimmt die Gruppe. |
Rückgabewert
null. Es hat für jeden Gruppenschlüssel eine Eigenschaft, deren Wert ein Array mit den Elementen der Gruppe ist. Innerhalb der Gruppe bleibt die ursprüngliche Reihenfolge erhalten.Beispiele
Bestellungen nach Status gruppieren
const orders = [
{ id: 1, status: 'offen', total: 49.9 },
{ id: 2, status: 'versandt', total: 19.5 },
{ id: 3, status: 'offen', total: 120 },
{ id: 4, status: 'storniert', total: 5 }
];
const byStatus = Object.groupBy(orders, ({ status }) => status);
console.log(Object.keys(byStatus));
console.log(byStatus.offen.map(o => o.id));
Nach berechneter Kategorie gruppieren
const products = [
{ name: 'Kabel', price: 4 },
{ name: 'Maus', price: 25 },
{ name: 'Monitor', price: 219 },
{ name: 'Adapter', price: 9 }
];
const byPriceRange = Object.groupBy(products, ({ price }) =>
price < 10 ? 'günstig' : price < 100 ? 'mittel' : 'teuer'
);
for (const [range, items] of Object.entries(byPriceRange)) {
console.log(range, items.map(p => p.name).join(', '));
}
Beliebige Iterables und Prototyp null
const numbers = new Set([1, 2, 3, 4, 5, 6]);
const parity = Object.groupBy(numbers, n => (n % 2 === 0 ? 'gerade' : 'ungerade'));
console.log(parity.gerade); // [2, 4, 6]
console.log(Object.getPrototypeOf(parity)); // null
// parity.hasOwnProperty('gerade') würde einen TypeError werfen:
console.log(Object.hasOwn(parity, 'gerade'));
Polyfill-Fallback mit reduce()
const groupBy = Object.groupBy ?? ((items, fn) => {
const result = Object.create(null);
let i = 0;
for (const item of items) {
const key = fn(item, i++);
(result[key] ??= []).push(item);
}
return result;
});
console.log(groupBy(['Apfel', 'Birne', 'Avocado'], w => w[0]));
// Wichtig · Fallstricke
- Kein
Object.prototype: Methoden wieresult.hasOwnProperty()oderresult.toString()gibt es nicht. NutzeObject.hasOwn(),Object.keys()oderObject.entries(). BeiString(result)oder Template-Literalen wirft der Aufruf einenTypeError. - Schlüssel werden in Strings umgewandelt:
1und'1'landen in derselben Gruppe. Objekte als Schlüssel werden alle zu"[object Object]". Für echte Objekt-Schlüssel nimmMap.groupBy(). - Reihenfolge der Schlüssel: Es gelten die normalen Regeln für Objekt-Eigenschaften. Ganzzahl-ähnliche Schlüssel (
"2","10") stehen aufsteigend sortiert vor den übrigen Strings, egal in welcher Reihenfolge sie aufgetreten sind. - Statisch, nicht auf dem Array: Aufgerufen wird
Object.groupBy(arr, fn). Einarr.groupBy()gibt es nicht. Frühe Entwürfe (Array.prototype.group) wurden wegen Web-Kompatibilitätsproblemen verworfen. - Kompatibilität: Ab ES2024 verfügbar (Chrome/Edge 117, Firefox 119, Safari 17.4, Node.js 21). Für ältere Umgebungen gibt es einen Polyfill (z. B.
core-js) oder eine Ersatzfunktion wie im Beispiel. In TypeScript musslibaufES2024oderESNextstehen. - Die Elemente werden nicht geklont. Wer ein Element in einer Gruppe ändert, ändert auch das Original.