# reduce

reduce walks through an array carrying a running total, so a whole list of scores, prices or plays boils down to one answer, such as a total, a count or a best score.

Journeyman · JavaScript · Updated November 1, 2026

## After this lesson you can

- Add up or count an array's items with reduce and a starting value
- Trace reduce step by step and say what the running total holds after each item

## Key takeaways

- reduce turns a whole array into one value, such as a total, a count or the best item.
- Its callback gets the running total so far and the current item, and returns the new running total.
- The second argument to reduce is the starting value. Give one every time, such as 0 for a total.
- With no starting value, reduce starts from the first item, which breaks on an empty array and on an array of objects.
- Whatever the callback returns becomes the running total for the next item, so a callback that forgets to return loses it.

The total at the bottom of a shopping cart. The red badge that says you have 7 unread messages. The "minutes listened" number in a music app's year-end summary. Each one is a single answer built from a whole list, and in JavaScript the method that builds it is `reduce`. It's the most powerful of the array methods, and the one that takes a little longer to click, so this lesson goes through it one step at a time.

The examples use the Comet Dash high-score list: gamer tags, scores, levels and the date each game was played.

## A tip jar: one value built from many

A coffee shop puts an empty tip jar on the counter in the morning. Every customer drops something in, and at closing time there's one total. The jar starts at zero, and each tip adds to what's already there.

`reduce` works like that jar. You give it a callback and a **starting value**. The callback gets two things, the total so far and the current item, and returns the new total:

```javascript
const scores = [8200, 12450, 3100];

const total = scores.reduce((sum, score) => sum + score, 0);

console.log(total);
```

```text
23750
```

Read it as "reduce the scores, starting from 0, by adding each score to the sum". The `0` after the callback is the starting value: the empty jar. The running total, `sum` here, is called the **accumulator** in textbooks and in the JavaScript documentation, because it accumulates (collects) the result.

## Step by step

reduce calls the callback once per item. Whatever the callback returns becomes `sum` the next time around:

| Call | `sum` (the running total) | `score` | The callback returns |
|---|---|---|---|
| 1st | 0 (the starting value) | 8200 | 8200 |
| 2nd | 8200 | 12450 | 20650 |
| 3rd | 20650 | 3100 | 23750 |

After the last item, reduce gives back what the last call returned: 23750. You can watch it happen by printing inside the callback:

```javascript
const scores = [8200, 12450, 3100];

const total = scores.reduce((sum, score) => {
  console.log(`sum is ${sum}, adding ${score}`);
  return sum + score;
}, 0);

console.log(`Total: ${total}`);
```

```text
sum is 0, adding 8200
sum is 8200, adding 12450
sum is 20650, adding 3100
Total: 23750
```

With curly braces, the callback needs its own `return`, as in *map and filter*. Forget it, and the callback returns `undefined`, which becomes the next `sum`: the running total is lost.

**Try it.** Make a file named `totals.js` with the code above, add a fourth score of 9900, and predict each line before you run `node totals.js`.

## Totals, counts and averages from records

On a list of player objects, the callback picks out the part it needs. Here one reduce adds up every score and another counts the players who reached level 5, adding 1 only when the player passes:

```javascript
const highScores = [
  { tag: "PixelPanda", score: 8200, level: 7 },
  { tag: "NovaFox", score: 12450, level: 9 },
  { tag: "CaptainCrumb", score: 3100, level: 3 },
  { tag: "LunaByte", score: 9900, level: 8 },
  { tag: "TurboSnail", score: 450, level: 1 },
];

const total = highScores.reduce((sum, player) => sum + player.score, 0);
const levelFivePlus = highScores.reduce((count, player) => (player.level >= 5 ? count + 1 : count), 0);

console.log(`Total: ${total}, average: ${total / highScores.length}`);
console.log(`Reached level 5: ${levelFivePlus}`);
```

```text
Total: 34100, average: 6820
Reached level 5: 3
```

The counting callback uses the conditional operator `? :` (read "if this, then that, otherwise that"): if the player reached level 5, the new count is one more, otherwise it stays the same. The average is the total divided by how many players there are.

## Always give a starting value

Leave the starting value out, and reduce uses the first item as the starting total and begins with the second item. That looks harmless on a list of numbers, but it breaks in two common cases. An empty array has no first item, so `[].reduce((sum, score) => sum + score)` stops with *TypeError: Reduce of empty array with no initial value*. And on a list of objects, the first "total" is a whole player object:

```javascript
const highScores = [
  { tag: "PixelPanda", score: 8200 },
  { tag: "NovaFox", score: 12450 },
];

const total = highScores.reduce((sum, player) => sum + player.score);

console.log(total);
```

```text
[object Object]12450
```

`sum` started as the PixelPanda object, and adding a number to an object turns both into text. With `, 0` at the end, the total starts at a number and the answer is 20650.

## Beyond numbers: building an object

The running total doesn't have to be a number. Start with an empty object `{}`, and reduce can count how many games were played on each date, the way a music app counts plays per song:

```javascript
const highScores = [
  { tag: "PixelPanda", date: "2026-10-03" },
  { tag: "NovaFox", date: "2026-10-05" },
  { tag: "CaptainCrumb", date: "2026-10-05" },
  { tag: "LunaByte", date: "2026-10-07" },
];

const gamesPerDay = highScores.reduce((counts, player) => {
  if (counts[player.date] === undefined) {
    counts[player.date] = 0;
  }
  counts[player.date] = counts[player.date] + 1;
  return counts;
}, {});

console.log(gamesPerDay);
```

```text
{ '2026-10-03': 1, '2026-10-05': 2, '2026-10-07': 1 }
```

Each date becomes a key the first time it turns up, and every game on that date adds one. This is the trick behind "your top artist this year": count the plays per artist with reduce, then find the biggest count.

## Check yourself

2 questions to try on the lesson page.

## So what

Whenever you need one answer from a whole list, a total, a count, a best score, or a tally of plays per day, reduce gets there in one pass: decide what the jar starts as, and what each item adds.

## Key terms

- [reduce()](https://www.ask-codey.com/glossary/reduce-javascript)
- Accumulator
- [Callback Function](https://www.ask-codey.com/glossary/callback-function)

## Cheat sheets

- [reduce](https://www.ask-codey.com/cheat-sheets/javascript-array-methods-reduce-cheat-sheet)

## Related

- [map and filter](https://www.ask-codey.com/lessons/javascript-array-methods-map-and-filter)
- [Sorting Arrays](https://www.ask-codey.com/lessons/javascript-array-methods-sort)

Source: https://www.ask-codey.com/lessons/javascript-array-methods-reduce
