map, filter, reduce: Array Methods for Beginners

October 6, 2026 · 3 min read

A lot of everyday code is loops over arrays: transform every item, keep some of them, add them up, find one. JavaScript has a method for each of those jobs. Once you know them, your code says what it's doing instead of how.

const orders = [5, 12, 8, 20]
 
const doubled = orders.map(n => n * 2)
const big = orders.filter(n => n > 10)
const total = orders.reduce((sum, n) => sum + n, 0)
const firstBig = orders.find(n => n > 10)
orders
[5, 12, 8, 20]

Four array methods cover most loops you will ever write. Each takes a callback and calls it once per item.

0 / 6

map: transform every item

const prices = [5, 12, 8, 20];
const doubled = prices.map((n) => n * 2);
// [10, 24, 16, 40]

map calls your function on each item and builds a new array of the results — always the same length as the original. The original array isn't changed.

The same thing with a loop, for comparison:

const doubled = [];
for (const n of prices) {
  doubled.push(n * 2);
}

Use map whenever you think "turn each X into a Y": numbers to strings, users to their names, data to list items.

const names = users.map((user) => user.name);

filter: keep some items

const big = prices.filter((n) => n > 10);
// [12, 20]

filter keeps the items for which your function returns true, in their original order. The result can be shorter than the original, never longer.

reduce: combine everything into one value

const total = prices.reduce((sum, n) => sum + n, 0);
// 45

reduce is the most powerful and the least obvious. It carries a running value — the accumulator — through the array:

  1. sum starts as the 0 you passed in.
  2. For each item, your function returns the new sum.
  3. After the last item, reduce returns the final sum.
0 + 5  = 5
5 + 12 = 17
17 + 8 = 25
25 + 20 = 45

Always pass the starting value (the 0). Without it, reduce uses the first item instead, and throws on an empty array.

reduce can build any kind of result — a number, an object, another array:

const countByCity = users.reduce((counts, user) => {
  counts[user.city] = (counts[user.city] ?? 0) + 1;
  return counts;
}, {});

find: get the first match

const firstBig = prices.find((n) => n > 10);
// 12

find returns the first item that matches and stops looking. If nothing matches, it returns undefined. Its cousins: findIndex (the position instead), some (is there at least one?) and every (do all of them match?).

Chaining

Because map and filter return new arrays, you can chain them:

const total = orders
  .filter((order) => order.status === 'paid')
  .map((order) => order.amount)
  .reduce((sum, amount) => sum + amount, 0);

Read it top to bottom: paid orders → their amounts → added up. Each step does one thing.

Cheat sheet

MethodQuestion it answersReturns
mapWhat does each item become?New array, same length
filterWhich items do I keep?New array, same or shorter
reduceWhat do they add up to?One value of any type
findWhich is the first match?One item, or undefined
some / everyDoes any / every item match?true or false
forEachDo something with each itemundefined

When to use a plain loop

  • You need to stop early in a way the methods don't support (though find and some do stop early).
  • You're doing something with side effects for each item — for…of is often clearer than forEach.
  • Performance-critical code over huge arrays, where creating intermediate arrays in a long chain adds up.

Common mistakes

  • Forgetting to return in a callback with braces: arr.map((n) => { n * 2 }) returns [undefined, …]. Either drop the braces or write return.
  • Using map just to loop. If you're not using the returned array, you wanted forEach or for…of.
  • Mutating inside map. Return new values instead of changing the originals.

These four methods each take a callback — a small function describing the work for one item — and handle the looping for you. That split is what makes them so readable.