reduce takes an entire array and combines everything into a single result: a number, an object, a string, anything.
You can read reduce: Boiling Down to One Value and try the first 1 exercise on the free plan. Upgrade to unlock the remaining 2 exercises and continue the full lesson flow.
Pro: every unit of every course · unlimited hearts · no weekly limit on assessment attempts
Complete lesson & earn 250 PX
EXERCISE
1While map returns an array and filter returns a subset, reduce takes an entire array and squashes it down into a single value: a number, a string, an object, anything.
reduce walks an array and combines everything into a single result. That result can be a number, a string, an object or another array. It is the most general of the three methods, and map and filter can both be written in terms of it.
const numbers = [5, 1, 3, 2, 6];
const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum); // 17
Two arguments, and the second is easy to miss because it sits outside the function. Read it first: 0 is the starting value of the accumulator.
Each call returns the new accumulator, and that return value arrives as accumulator on the next pass:
start: acc = 0
pass 1: acc = 0, current = 5 -> 5
pass 2: acc = 5, current = 1 -> 6
pass 3: acc = 6, current = 3 -> 9
pass 4: acc = 9, current = 2 -> 11
pass 5: acc = 11, current = 6 -> 17
Forgetting to return the accumulator is the mistake that produces the most confusing output:
const wrong = numbers.reduce((acc, n) => {
acc + n;
}, 0);
console.log(wrong); // undefined
The first pass returned undefined, which became the accumulator for the second pass, and so on. One missing return and the whole chain collapses.
Leaving out the initial value changes the behaviour:
console.log([5, 1, 3].reduce((a, b) => a + b)); // 9
console.log([].reduce((a, b) => a + b)); // TypeError: Reduce of empty array with no initial value
Without a starting value, the first element becomes the accumulator and iteration begins at the second. That works until the array is empty, at which point there is nothing to start from and it throws.
It also silently changes the result type when you are building something:
const nums = [1, 2, 3];
console.log(nums.reduce((acc, n) => acc + n, "")); // "123"
console.log(nums.reduce((acc, n) => acc + n, 0)); // 6
The accumulator's type is decided entirely by what you pass as the initial value. Always pass one.
reduce also receives the index and the source array, which is what lets it compute things that depend on position:
const scores = [10, 20, 30];
const average = scores.reduce((acc, n, i, arr) => {
const total = acc + n;
return i === arr.length - 1 ? total / arr.length : total;
}, 0);
console.log(average); // 20
This is the sort of thing reduce can do and map cannot, because each step has access to what came before it rather than only to its own element.
The accumulator carries forward between iterations. The initial value sets the output shape (0 for sums, for objects, [] for arrays). reduce can replicate map and filter.