Reference

Reference · Arrays

Array.prototype.reduce()

reduce() collapses an array into a single value — a sum, a lookup object, a grouped structure — by running a function that carries an accumulator across every element.

XCODXReference · Updated

Definition

Array.prototype.reduce() runs a function against every element of an array, carrying a running result — the accumulator — from one call to the next, and returns the final accumulator. It's the most general array method: map() and filter() can both be expressed with reduce(), though you should reach for them first when they fit.

Use reduce() when you need to fold a whole array into one value whose type may differ from the elements: a number (sum, max), an object (a tally, a lookup, groups), or a string.

Syntax

array.reduce(callbackFn)
array.reduce(callbackFn, initialValue)

array.reduce((accumulator, currentValue, currentIndex, array) => {
  return /* the next accumulator */;
}, initialValue)

Whatever the callback returns becomes the accumulator for the next element. The value returned on the last element is the result of reduce().

Parameters

ParameterRequiredDescription
callbackFnYesFunction run for each element; its return value is the accumulator passed to the next call.
accumulatorThe running result — initialValue on the first call, then each call's return value.
currentValueThe current element being processed.
currentIndexThe index of the current element.
arrayThe array reduce() was called on.
initialValueNoStarting accumulator. If omitted, the first element is used as the initial accumulator (see below).

Return value

The single accumulated value returned by the final call to callbackFn. reduce() does not mutate the original array.

With vs. without initialValue

This is the part that trips people up. Passing initialValue is almost always the right choice:

With initialValueWithout initialValue
First accumulatorinitialValuearray[0]
First currentValuearray[0]array[1]
First index processed01
Empty arrayreturns initialValuethrows TypeError

Examples

Sum the elements

Find the maximum

const max = [3, 7, 2, 9, 4].reduce((best, n) => (n > best ? n : best));
console.log(max); // 9
// (Math.max(...arr) is simpler here — reduce shines when the logic is custom.)

Tally occurrences into an object

A perfect fit for reduce(): fold a list into a count map. The initial value is an empty object.

const votes = ['a', 'b', 'a', 'c', 'b', 'a'];

const counts = votes.reduce((acc, vote) => {
  acc[vote] = (acc[vote] || 0) + 1;
  return acc;
}, {});

console.log(counts); // { a: 3, b: 2, c: 1 }

Group items by a key

const people = [
  { name: 'Ada', team: 'A' },
  { name: 'Bo', team: 'B' },
  { name: 'Cy', team: 'A' },
];

const byTeam = people.reduce((acc, person) => {
  acc[person.team] = acc[person.team] || [];
  acc[person.team].push(person.name);
  return acc;
}, {});

console.log(byTeam); // { A: ['Ada', 'Cy'], B: ['Bo'] }

Browser & runtime support

When NOT to use reduce()

reduce() is powerful, but a simpler, clearer method is often the better tool. Prefer these when they fit:

GoalReach for
Transform each elementmap()
Keep some elementsfilter()
Flatten nested arraysflat() / flatMap()
Remove duplicatesnew Set(array)
Find one elementfind(), some(), every()
Sum of numbersreduce() (this is its sweet spot)

Availability

reduce() has been part of the language since ECMAScript 5 (2009) and works in every modern browser and every maintained version of Node.js.

Frequently asked questions

Should I always pass an initialValue?
Almost always yes. It makes the accumulator's type explicit, starts iteration at index 0, and — crucially — returns the initial value instead of throwing when the array is empty.
Why does reduce() throw 'Reduce of empty array with no initial value'?
With no initialValue, reduce() uses the first element as the starting accumulator. An empty array has no first element, so there is nothing to start from and it throws a TypeError. Pass an initialValue to avoid this.
Is reduce() slower than a for loop?
For a single pass they're comparable. Reduce becomes slow only when the callback copies the accumulator each iteration (spread/concat), which introduces O(n²) work. Mutate-and-return the accumulator to keep it O(n).
Can reduce() replace map() and filter()?
Technically yes — you can build any array transformation with reduce(). But map() and filter() are clearer for their specific jobs, so use them when they fit and save reduce() for folding into a single value.