Start · Sprachen · JavaScript · Referenz · Object.groupBy()

Object.groupBy()

Methode

Gruppiert die Elemente eines iterierbaren Objekts in ein Objekt ohne Prototyp. Als Schlüssel dienen die Werte, die die Callback-Funktion zurückgibt.

seit JavaScript ES2024 (Baseline 2024: Chrome 117, Firefox 119, Sa Kategorie: method-property

Signatur

Object.groupBy(items, callbackFn)

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

Typ
Object (Prototyp null) mit Einträgen der Form { [key: string]: T[] }
Beschreibung
Ein Objekt mit dem Prototyp 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));
[ 'offen', 'versandt', 'storniert' ] [ 1, 3 ]

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(', '));
}
günstig Kabel, Adapter mittel Maus teuer Monitor

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'));
[ 2, 4, 6 ] null true

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]));
[Object: null prototype] { A: [ 'Apfel', 'Avocado' ], B: [ 'Birne' ] }

// Wichtig · Fallstricke

  • Kein Object.prototype: Methoden wie result.hasOwnProperty() oder result.toString() gibt es nicht. Nutze Object.hasOwn(), Object.keys() oder Object.entries(). Bei String(result) oder Template-Literalen wirft der Aufruf einen TypeError.
  • Schlüssel werden in Strings umgewandelt: 1 und '1' landen in derselben Gruppe. Objekte als Schlüssel werden alle zu "[object Object]". Für echte Objekt-Schlüssel nimm Map.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). Ein arr.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 muss lib auf ES2024 oder ESNext stehen.
  • Die Elemente werden nicht geklont. Wer ein Element in einer Gruppe ändert, ändert auch das Original.