Both are static methods that replace the hand-written reduce grouping loop:
Object.groupBy(items, (item, index) => key)
Map.groupBy(items, (item, index) => key)
The shared GroupBy operation in the spec: it requires items to be iterable (GetIterator), requires callback to be callable (TypeError otherwise), and calls the callback once per element in order with (value, index). Elements go into an array per key, in encounter order. If the callback throws, the iterator is closed.
They differ only in how the key is treated:
Object.groupBy |
Map.groupBy |
|
|---|---|---|
| Key handling | ToPropertyKey (string or symbol) |
kept as is; SameValueZero, -0 becomes 0 |
| Result | object with a null prototype |
Map |
| Group order | integer-like keys ascending, then creation order | strictly first-seen order |
Choose by the key. Use Object.groupBy when keys are strings or symbols and you want property access or JSON (byType.fruit). Use Map.groupBy when keys are numbers you care about as numbers, objects, NaN, or you need first-seen order and a size.
The null prototype means 'toString' in result is false, so a group named constructor or __proto__ is safe, but result.hasOwnProperty does not exist; use Object.hasOwn(result, key).
The arrays hold the original element references, not copies. The methods do not mutate the input, and they are for synchronous iterables only.
Support: Object.groupBy is Baseline widely available (since March 2024, MDN); the examples below ran in Node 24.