JavaScript Array Methods: map, filter, reduce
Master the three most powerful array methods in JavaScript — map, filter, and reduce — with practical examples, chaining patterns, and performance tips.
What you'll learn
- ✓How map transforms every element
- ✓How filter selects elements by predicate
- ✓How reduce folds an array into one value
- ✓Chaining for readable pipelines
- ✓When to fall back to a plain for loop
Prerequisites
- •Familiarity with JavaScript basics
The map, filter, and reduce methods are the backbone of functional-style array processing in JavaScript. Together they replace most loops in modern code. This tutorial covers each one with practical examples, then shows how to compose them into elegant data pipelines.
map: Transform Every Element
map produces a new array of the same length by running a function on each element. The original array is untouched. This is your tool whenever you need to convert one shape into another.
const prices = [10, 20, 30];
const withTax = prices.map(p => p * 1.2);
console.log(withTax); // [12, 24, 36]
The callback receives three arguments: the current element, its index, and the source array. The index is handy when you need positional information.
const names = ['Ada', 'Bob', 'Cory'];
const labelled = names.map((name, i) => `${i + 1}. ${name}`);
Always return a value from a map callback. Forgetting to return is the most common bug.
filter: Keep What Matches
filter builds a new array containing only the elements for which the callback returns a truthy value. It is the cleanest way to narrow down a list.
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4]
A common pattern is removing falsy values from a sparse list. Passing the Boolean constructor as the predicate works as a concise idiom.
const items = ['a', null, 'b', undefined, 'c'];
const clean = items.filter(Boolean);
Remember that filter always returns a new array, even if no element matches — it just returns an empty one.
reduce: Fold to a Single Value
reduce is the most powerful and the most intimidating of the trio. It walks the array while accumulating a single result. The callback takes the accumulator and the current element.
const total = [10, 20, 30].reduce((sum, n) => sum + n, 0);
console.log(total); // 60
The second argument to reduce is the initial accumulator value. Always provide it — relying on the implicit first-element default makes empty arrays throw.
You can use reduce to build any data shape, not just numbers. Here we group users by role.
const users = [
{ name: 'Ada', role: 'admin' },
{ name: 'Bob', role: 'user' },
{ name: 'Cory', role: 'admin' },
];
const byRole = users.reduce((acc, user) => {
(acc[user.role] ||= []).push(user);
return acc;
}, {});
If reading reduce code makes your eyes glaze, you are not alone. Pull complex reducers into a named helper function for readability.
Chaining Pipelines
The real power emerges when you chain these methods. Each step is independent and reads top-to-bottom like a pipeline.
const orders = [
{ id: 1, total: 50, status: 'paid' },
{ id: 2, total: 80, status: 'pending' },
{ id: 3, total: 30, status: 'paid' },
];
const paidRevenue = orders
.filter(o => o.status === 'paid')
.map(o => o.total)
.reduce((sum, t) => sum + t, 0);
console.log(paidRevenue); // 80
Each method allocates a new intermediate array, which is fine for most data but can matter for very large lists.
Immutability Wins
Because these methods do not mutate the source array, they pair perfectly with frameworks like React that rely on reference equality. Replacing an in-place sort or splice with map/filter makes state updates predictable.
// Instead of splice
const removed = items.filter(item => item.id !== targetId);
This habit dramatically reduces “why did my component not rerender?” bugs.
When to Use a for Loop
Sometimes a plain for or for...of loop is better. If you need early termination, a for loop with break is more efficient than scanning the entire array. The find and some methods handle simple early-exit cases, but complex multi-step logic often reads better in a procedural loop.
For ten million elements, a for loop with index access also tends to be measurably faster, though for most real apps the difference is invisible.
Wrapping Up
Learning map, filter, and reduce is one of the highest-leverage things you can do as a JavaScript developer. They make code shorter, safer, and more declarative. Practice chaining them, and watch your data-processing code transform.
Related articles
- JavaScript JavaScript Arrays: Create, Iterate, Transform
A complete beginner's guide to JavaScript arrays — creation, indexing, the essential mutation methods, iteration, map/filter/reduce, and a first look at spread and destructuring.
- JavaScript The JavaScript Event Loop, Explained Clearly
A deep but practical look at the JavaScript event loop: call stack, microtasks, macrotasks, and how async code actually runs in the browser and Node.
- JavaScript JavaScript Generators and Iterators
A practical guide to JavaScript iterators and generator functions: the protocols, lazy sequences, async generators, and where they shine in real code.
- JavaScript JavaScript Modules: ESM vs CommonJS
A practical comparison of ES Modules and CommonJS: how they load, how they differ, interop strategies, and how to choose for a new project.