Array.prototype.reduce()
The general-purpose one: map, filter and join can all be written with it. Omitting the initial value is what turns it from useful into a source of runtime errors.
Demo
The callback receives the running accumulator and the next element, and whatever it returns becomes the accumulator for the next round. Starting from 10 rather than 0 simply shifts the result by 10. The empty case is the one that matters: because an initial value is supplied, it comes straight back rather than throwing — which is exactly what happens without one.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| callback | Function | yes | Called as callback(accumulator, element, index, array). Its return value becomes the accumulator for the next element. |
| initialValue | any | no (first element) | Starting accumulator. Omitted, the first element is used and iteration starts at the second — which is why an empty array then throws. |
Return value
any — Whatever the callback returned on the final iteration. With an initialValue and an empty array, that value is returned untouched.
Common patterns
const total = prices.reduce((acc, p) => acc + p, 0);
const byType = items.reduce((acc, i) => { (acc[i.type] ??= []).push(i); return acc; }, {});
const counts = words.reduce((acc, w) => { acc[w] = (acc[w] ?? 0) + 1; return acc; }, {});
Examples
Pitfalls
[].reduce((a, b) => a + b)
[].reduce((a, b) => a + b, 0)
[1, 2].reduce((acc, x) => { acc.total = x; }, {})
[1, 2].reduce((acc, x) => { acc.total = x; return acc; }, {})
items.reduce((o, k) => ({...o, [k]: true}), {})
items.reduce((o, k) => { o[k] = true; return o; }, {})
items.reduce((acc, x) => [...acc, x * 2], [])
items.map(x => x * 2)
When to use
- Summing or otherwise aggregating to a single value
- Building an object or Map from an array in one pass
- Counting or grouping
- Any fold where the accumulator type differs from the element type
- One-to-one transformation → map
- Selecting a subset → filter
- Joining into a string → join
- The accumulator is just a growing array → map or flatMap
Notes
FAQ
Yes, unless you have already proved the array is non-empty. It costs nothing, it removes the empty-array TypeError entirely, and it makes the accumulator type obvious to the next reader.
items.reduce((a, b) => a + b, 0)