reduce() goes through an array and combines it into one value: a sum, a count, an object, even another array. It looks tricky at first, so let’s build it up slowly.
A sum, with a loop first
const numbers = [1, 2, 3, 4];
let total = 0;
for (const n of numbers) {
total += n;
}
console.log(total); // → 10
Now the same with reduce:
const numbers = [1, 2, 3, 4];
const total = numbers.reduce((sum, n) => sum + n, 0);
console.log(total); // → 10
The two ingredients
array.reduce((accumulator, item) => newAccumulator, initialValue)
- The accumulator is the value being built up. It carries the result between steps.
- The callback receives the accumulator and the next item, and returns the new accumulator.
- The initial value (the last argument) is where the accumulator starts.
Here is what happens for [1, 2, 3, 4] with a start of 0:
| Step | accumulator | item | returns |
|---|---|---|---|
| 1 | 0 | 1 | 1 |
| 2 | 1 | 2 | 3 |
| 3 | 3 | 3 | 6 |
| 4 | 6 | 4 | 10 |
Always give an initial value
Without it, reduce uses the first item as the start, and throws an error on an empty array.
console.log([].reduce((a, b) => a + b, 0)); // → 0
Other uses
Counting things:
const votes = ["yes", "no", "yes", "yes", "no"];
const count = votes.reduce((totals, vote) => {
totals[vote] = (totals[vote] ?? 0) + 1;
return totals;
}, {});
console.log(count); // → { yes: 3, no: 2 }
Totalling objects:
const cart = [
{ name: "Book", price: 12, qty: 2 },
{ name: "Pen", price: 2, qty: 5 }
];
const total = cart.reduce((sum, item) => sum + item.price * item.qty, 0);
console.log(total); // → 34
Finding the maximum:
console.log([4, 9, 2].reduce((max, n) => (n > max ? n : max), -Infinity)); // → 9
When not to use reduce
If a simpler method does the job, use it: Math.max(...numbers), filter().length, join(). A long reduce is hard to read, and a plain for...of loop is better than a clever reduce.