Ch. 1 · JavaScript

JavaScript Reduce Without Hidden Mutation

JavaScript Reduce Without Hidden Mutation. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readintermediateupdated Oct 3, 2026

Reduce combines input into an accumulator with a stated invariant. Supply an initial value when empty input is valid.

Step-by-step walkthrough

Step 1: State the accumulator invariant

Explain what the accumulator contains after processing the first i elements. A sum holds their total; a group map holds each category’s processed records. This makes the initial value and update operation consequences of the problem instead of memorized syntax.

Step 2: Supply the identity value

Choose an initial accumulator that correctly describes zero processed elements. For numeric addition that is zero. For grouping it is an empty collection. Without an initial value, the first element becomes the accumulator and empty input has no valid starting point.

Step 3: Inspect copying and ownership

Repeatedly copying a growing accumulator can turn a linear traversal into quadratic work. Mutating a newly created local accumulator can be safe when it is not externally shared. Avoid mutating caller-owned records merely to make the reduce callback shorter.

Worked scenario

Start a price total at zero. Group records into a fresh Map rather than repeatedly spreading a growing object.

const orders = [{total: 10}, {total: 20}];
const total = orders.reduce((sum, order) => sum + order.total, 0);
console.log(total); // 30
console.log([].reduce((sum, value) => sum + value, 0)); // 0
const groups = orders.reduce((map, order) => {
  const key = order.total >= 20 ? 'large' : 'small';
  const group = map.get(key) ?? [];
  group.push(order);
  map.set(key, group);
  return map;
}, new Map());
JavaScript

Walk through the example

The total’s invariant is the sum of processed totals. The group reducer owns its fresh Map and arrays, making local mutation deliberate. It still stores references to original orders. The initial values define empty-input behavior and keep the resulting accumulator shapes predictable.

Common mistake

Repeated copying can make an otherwise linear loop quadratic. Local accumulator mutation differs from mutating caller input.

Verify the behavior

Check empty input, one item and multiple groups. For totals, validate whether malformed numbers should throw before reduction. For grouping, assert every input appears in exactly one intended group and that the original collection is unchanged.

Interview exercise

Explain empty-array reduction.

Answer and reasoning

Without an initial value there is no first accumulator. An identity value defines the empty case explicitly.

Follow-up discussion

Should every loop become reduce? No: clarity, early exit and error handling may favor an explicit loop. When is spreading the accumulator costly? When each iteration copies all previous entries, total copying grows with the sum of intermediate sizes rather than just input length.

Continue learning

Compare the scenario with the JavaScript interview questions and test your understanding with the JavaScript MCQs. For terminology and implementation details, consult the reference material.

More in JavaScript

read ✓JavaScript · easy

JavaScript Array Copies and Shared Objects

JavaScript Array Copies and Shared Objects. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readread →
read ✓JavaScript · mid

JavaScript Date and Timezone Pitfalls

Parse and format dates without timezone surprises: zero-based months, date-only versus date-time parsing, and why UTC storage avoids drift.

~3 min readread →
esc