JavaScript Reduce- Complete Guide with Examples

What is JavaScript Reduce?

The reduce() method is an array method that processes each element and returns a single value. It takes a callback function and an optional initial value.

Most developers encounter it and freeze up. The syntax looks intimidating. The documentation talks about "accumulators" and "reducers" like you're writing a math proof.

It's not that complicated. Reduce is just a loop that carries a running value forward.

The Basic Syntax

array.reduce(callback, initialValue)

The callback receives four arguments:

The Simplest Example First

Sum all numbers in an array:

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((acc, curr) => acc + curr, 0);

console.log(sum); // 15

Walk through what happens:

The initial value matters. Without it, the first iteration uses the first element as the accumulator. This causes bugs when your array is empty or when the first element isn't a valid starting point.

Common Use Cases

Counting Occurrences

const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];

const count = fruits.reduce((acc, fruit) => {
  acc[fruit] = (acc[fruit] || 0) + 1;
  return acc;
}, {});

console.log(count);
// { apple: 3, banana: 2, orange: 1 }

Grouping Objects by a Property

const people = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 25 }
];

const grouped = people.reduce((acc, person) => {
  const key = person.age;
  if (!acc[key]) acc[key] = [];
  acc[key].push(person);
  return acc;
}, {});

console.log(grouped);
// { 25: [Alice, Charlie], 30: [Bob] }

Flattening Nested Arrays

const nested = [[1, 2], [3, 4], [5, 6]];

const flat = nested.reduce((acc, curr) => acc.concat(curr), []);

console.log(flat); // [1, 2, 3, 4, 5, 6]

Finding the Maximum Value

const scores = [72, 95, 84, 61, 99, 78];

const max = scores.reduce((acc, curr) => curr > acc ? curr : acc, scores[0]);

console.log(max); // 99

Or simpler with Math.max and spread:

const max = scores.reduce((acc, curr) => Math.max(acc, curr), -Infinity);

Chaining Reduce with Other Methods

Reduce shines when combined with other array methods. You can transform, filter, and aggregate in a single chain.

const products = [
  { name: 'Laptop', price: 999, category: 'electronics' },
  { name: 'Shirt', price: 29, category: 'clothing' },
  { name: 'Phone', price: 699, category: 'electronics' },
  { name: 'Pants', price: 49, category: 'clothing' }
];

// Get total electronics revenue
const total = products
  .filter(p => p.category === 'electronics')
  .reduce((acc, curr) => acc + curr.price, 0);

console.log(total); // 1698

Reduce vs Other Array Methods

You don't always need reduce. Sometimes map or filter does the job cleaner.

Method Returns Use When
map Array Transforming each element
filter Array Selecting elements that match a condition
reduce Single value (any type) Aggregating, accumulating, or building something new

If you're returning an array of the same length, use map. If you're returning a subset, use filter. If you're building something that doesn't map 1:1, use reduce.

Common Mistakes

Forgetting the Initial Value

// Wrong - accumulator starts at first element
const sum = [1, 2, 3].reduce((acc, curr) => acc + curr);
// Returns 6, but breaks on empty arrays

// Correct - explicit initial value
const sum = [1, 2, 3].reduce((acc, curr) => acc + curr, 0);
// Returns 6, handles empty arrays gracefully

Not Returning the Accumulator

// Wrong - forgot to return
const doubled = [1, 2, 3].reduce((acc, curr) => {
  acc.push(curr * 2);
  // Missing: return acc;
});

// Correct - always return the accumulator
const doubled = [1, 2, 3].reduce((acc, curr) => {
  acc.push(curr * 2);
  return acc;
}, []);

Mutating Objects When You Shouldn't

If you're building an object, create a new one on each iteration unless you intentionally want mutation. Deep cloning inside reduce kills performance on large datasets.

Getting Started: Your First Reduce

Try this exercise. Given an array of transactions:

const transactions = [
  { type: 'credit', amount: 100 },
  { type: 'debit', amount: 50 },
  { type: 'credit', amount: 75 },
  { type: 'debit', amount: 30 }
];

Calculate the balance. Answer:

const balance = transactions.reduce((acc, t) => {
  return t.type === 'credit' ? acc + t.amount : acc - t.amount;
}, 0);

console.log(balance); // 95

Start with simple aggregations. Count things. Sum things. Build objects. Once the pattern clicks, you'll find reduce useful in places you used to write for loops.