# What Is the Difference Between Map, Filter, and Reduce in JavaScript?

> Understand the differences between JavaScript map filter and reduce array methods Learn when to use each to transform filter or accumulate array elements while maintaining immutability

- Repository: [Leonardo Maldonado/33-js-concepts](https://github.com/leonardomso/33-js-concepts)
- Tags: deep-dive
- Published: 2026-03-03

---

**`map` transforms every element into a new array of equal length, `filter` creates a new array containing only elements that pass a test, and `reduce` accumulates all elements into a single value—while all three preserve the original array's immutability.**

The `leonardomso/33-js-concepts` repository demonstrates these core array methods through rigorous test cases in [`tests/functional-programming/map-reduce-filter/map-reduce-filter.test.js`](https://github.com/leonardomso/33-js-concepts/blob/main/tests/functional-programming/map-reduce-filter/map-reduce-filter.test.js). Understanding the distinct return values and iteration patterns of each method enables you to select the right tool for data transformation, selection, or aggregation tasks without mutating source data.

## How Each Method Transforms Data

All three methods are **higher-order functions** that accept a callback and execute it once per array element. According to the immutability assertions in lines 13-19 of [`map-reduce-filter.test.js`](https://github.com/leonardomso/33-js-concepts/blob/main/map-reduce-filter.test.js), the original array remains `[1,2,3]` after any operation completes.

### Array.prototype.map(): One-to-One Transformation

The `map()` method returns a **new array** where each element is the result of invoking your callback on the corresponding original element. The output length always matches the input length, making it ideal for property extraction or calculations.

Use `map` when converting an array of objects into values, as demonstrated in lines 5-11 of the test suite:

```javascript
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2);
// Result: [2, 4, 6, 8]

```

### Array.prototype.filter(): Subset Selection

The `filter()` method returns a **new array** containing only elements for which your callback returns a **truthy** value. This effectively selects a subset of data based on a predicate condition.

Use `filter` when you need to remove unwanted items, such as extracting even numbers shown in lines 25-27:

```javascript
const numbers = [1, 2, 3, 4, 5, 6];
const evens = numbers.filter(n => n % 2 === 0);
// Result: [2, 4, 6]

```

### Array.prototype.reduce(): Aggregation and Folding

The `reduce()` method returns a **single value**—which can be a number, object, or another array—by applying your callback to each element in sequence. It maintains an **accumulator** that carries the running result between iterations.

Use `reduce` for aggregation tasks like summing values or building lookup maps. The callback receives `(accumulator, element, index, array)` and must return the new accumulator value. Lines 68-73 demonstrate basic summation:

```javascript
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, n) => acc + n, 0);
// Result: 15

```

If you omit the `initialValue` parameter, `reduce` uses the first array element as the initial accumulator and skips the first iteration.

## When to Use Each Method

Choosing the correct method clarifies your code's intent and prevents over-engineering. The test suite in `leonardomso/33-js-concepts` identifies specific decision points:

- **Transform data shape**: Use `map` to extract properties or calculate derived values (e.g., `user => user.name`).
- **Select valid entries**: Use `filter` to keep items matching criteria (e.g., active users, positive numbers).
- **Compute totals or build objects**: Use `reduce` for aggregation (sum, average) or complex grouping. Lines 20-27 demonstrate a group-by-property implementation where `reduce` builds a map of arrays (`{key: [items]}`).

### Chaining for Complex Pipelines

For multi-step operations, chain the methods rather than creating a monolithic `reduce`. Lines 26-31 demonstrate a real-world pipeline that filters in-stock products, maps to prices, then reduces to a total:

```javascript
const products = [
  { name: 'Laptop', price: 1000, inStock: true },
  { name: 'Phone',  price: 500,  inStock: false },
  { name: 'Tablet', price: 300,  inStock: true }
];

const totalInStock = products
  .filter(p => p.inStock)
  .map(p => p.price)
  .reduce((sum, price) => sum + price, 0);
// Result: 1300

```

Lines 50-68 specifically caution against cramming filter-and-map logic into a single `reduce` block, as this reduces readability while providing no performance benefit in modern JavaScript engines.

### Advanced Reduce Patterns

Because `reduce` is the most flexible method, you can theoretically implement the others with it—though you shouldn't in production code. Lines 46-55 demonstrate implementing `map` using `reduce` to illustrate the underlying mechanics:

```javascript
const doubled = numbers.reduce((acc, n) => {
  acc.push(n * 2);
  return acc;
}, []);

```

## Summary

- **`map`** returns a new array of equal length, transforming each element individually—ideal for property extraction or calculations.
- **`filter`** returns a new array of variable length, keeping only elements where the callback returns truthy—use for subset selection.
- **`reduce`** returns any single value by accumulating results across iterations—essential for aggregation, grouping, or folding operations.
- **Immutability**: All three methods leave the source array untouched, as verified by the test assertions in lines 13-19 of [`map-reduce-filter.test.js`](https://github.com/leonardomso/33-js-concepts/blob/main/map-reduce-filter.test.js).
- **Readability**: Prefer chaining `filter` → `map` → `reduce` over complex single-reduce solutions that mix concerns.

## Frequently Asked Questions

### Can I use reduce instead of map or filter?

Technically yes, but you shouldn't. Lines 46-55 of [`map-reduce-filter.test.js`](https://github.com/leonardomso/33-js-concepts/blob/main/map-reduce-filter.test.js) prove that `reduce` can implement `map` by pushing to an accumulator array. However, using `map` or `filter` explicitly communicates your intent and makes the code self-documenting. Reserve `reduce` for true aggregation tasks.

### Do map, filter, and reduce mutate the original array?

No. All three methods return new values and leave the source array unchanged. The repository's immutability tests (lines 13-19) assert that the original array stays `[1,2,3]` after any operation, confirming these are pure functional utilities.

### Is it better to chain methods or use a single reduce?

For readability, chain methods. Lines 50-68 demonstrate that while a single `reduce` can perform filtering and mapping simultaneously, separating concerns into `filter().map().reduce()` creates clearer, more maintainable code. Each method traverses the array once, and modern JavaScript engines optimize chained operations effectively.

### What happens if I call reduce on an empty array without an initial value?

JavaScript throws a `TypeError`. The `reduce` method requires an `initialValue` when the array is empty because it cannot determine an initial accumulator. Always provide an `initialValue` argument (such as `0` for sums or `[]` for arrays) when the input array might be empty to avoid runtime errors.