Array methods: map, filter, reduce, find and more

Transform, search and summarise arrays with built-in methods, chain them into readable pipelines, and know which ones change the original.

  • Beginner
  • 6 min read
  • Updated 17 Oct 2026

What you will learn

  • Transform data with map and filter
  • Summarise data with reduce
  • Search arrays with find, some, every and includes
  • Tell mutating methods from non-mutating ones

Before you start

Most work with data is the same few jobs: change every item, keep some items, find one item, or boil a list down to a single value. Arrays have a built-in method for each job. Using them makes your intent obvious in one word, where a for loop makes the reader work it out.

All examples in this lesson use this array:

JavaScript
const lessons = [
  { title: 'Variables', minutes: 12, level: 'Beginner', done: true },
  { title: 'Closures', minutes: 20, level: 'Intermediate', done: false },
  { title: 'Array methods', minutes: 25, level: 'Intermediate', done: false },
  { title: 'Functions', minutes: 20, level: 'Beginner', done: true },
];

How callbacks work here

Each method takes a callback and calls it once per item, passing three arguments: the item, its index and the whole array. You usually need only the first.

JavaScript
lessons.forEach((lesson, index) => {
  console.log(`${index + 1}. ${lesson.title}`);
});
// → 1. Variables
// → 2. Closures
// → 3. Array methods
// → 4. Functions

forEach runs code for each item and returns undefined. Use it for side effects such as logging or updating the page. When you want a result, use one of the methods below.

map: transform every item

map returns a new array of the same length, built from whatever the callback returns:

JavaScript
const titles = lessons.map((lesson) => lesson.title);
console.log(titles);
// → ['Variables', 'Closures', 'Array methods', 'Functions']

const labels = lessons.map((lesson) => `${lesson.title} (${lesson.minutes} min)`);
console.log(labels[0]); // → Variables (12 min)

If you forget to return inside a callback with braces, every item becomes undefined:

JavaScript
const oops = lessons.map((lesson) => { lesson.title; });
console.log(oops); // → [undefined, undefined, undefined, undefined]

filter: keep some items

filter returns a new array containing only the items for which the callback returns a truthy value:

JavaScript
const todo = lessons.filter((lesson) => !lesson.done);
console.log(todo.length); // → 2

const beginner = lessons.filter((lesson) => lesson.level === 'Beginner');
console.log(beginner.map((lesson) => lesson.title));
// → ['Variables', 'Functions']

If nothing matches, you get an empty array, never undefined.

find and findIndex: get one item

find returns the first matching item, or undefined if none matches. It stops as soon as it finds one.

JavaScript
const closures = lessons.find((lesson) => lesson.title === 'Closures');
console.log(closures.minutes); // → 20

const missing = lessons.find((lesson) => lesson.title === 'Regex');
console.log(missing); // → undefined

findIndex returns the position instead, or -1. findLast and findLastIndex search from the end and are supported in all current browsers and Node.js 20.

some, every and includes: yes or no

JavaScript
console.log(lessons.some((lesson) => lesson.done));         // → true
console.log(lessons.every((lesson) => lesson.minutes < 30)); // → true

const levels = ['Beginner', 'Intermediate', 'Advanced'];
console.log(levels.includes('Advanced')); // → true

some answers "is at least one?", every answers "are all?", and includes checks for a value using strict equality (with the one exception that it does find NaN). Use includes for simple values and some when you need a condition.

reduce: boil down to one value

reduce walks the array carrying an accumulator. The callback receives the accumulator and the current item, and returns the new accumulator. The second argument to reduce is the starting value.

JavaScript
const totalMinutes = lessons.reduce((total, lesson) => total + lesson.minutes, 0);
console.log(totalMinutes); // → 77

Step by step: 0 + 12, then 12 + 20, then 32 + 25, then 57 + 20.

The accumulator can be any type. Here it is an object that counts lessons per level:

JavaScript
const perLevel = lessons.reduce((counts, lesson) => {
  counts[lesson.level] = (counts[lesson.level] ?? 0) + 1;
  return counts;
}, {});

console.log(perLevel); // → { Beginner: 2, Intermediate: 2 }

The ?? operator supplies 0 the first time a level appears; lesson 25 covers it.

Always pass a starting value. Without one, reduce uses the first item as the accumulator and throws a TypeError on an empty array.

reduce can do anything, which is exactly why it can be hard to read. If map, filter or a short for...of loop says the same thing, prefer those. For grouping, Object.groupBy(lessons, (lesson) => lesson.level) is a newer built-in for exactly this job. It is in all current browsers but not in Node.js 20, so check support on MDN before relying on it.

Chaining

Because map and filter return arrays, you can chain them into a pipeline that reads top to bottom:

JavaScript
const remaining = lessons
  .filter((lesson) => !lesson.done)
  .map((lesson) => lesson.title)
  .join(', ');

console.log(remaining); // → Closures, Array methods

Each step creates a new array. For the lists you show on a page, that cost is negligible; readability matters more.

Sorting

sort takes a compare function that returns a negative number if a comes first, a positive number if b comes first, and 0 if they are equal:

JavaScript
const byLength = [...lessons].sort((a, b) => a.minutes - b.minutes);
console.log(byLength.map((lesson) => lesson.minutes)); // → [12, 20, 20, 25]

const byTitle = [...lessons].sort((a, b) => a.title.localeCompare(b.title));
console.log(byTitle[0].title); // → Array methods

Without a compare function, sort converts items to strings and compares them, so numbers sort wrongly:

JavaScript
console.log([10, 9, 1].sort()); // → [1, 10, 9]

Which methods mutate?

Some methods change the array they are called on. That matters when other code holds the same array (lesson 40 explains why).

Changes the originalReturns a new array or value
push, pop, shift, unshiftmap, filter, slice, concat
splicetoSpliced
sorttoSorted
reversetoReversed
fill, copyWithinwith(index, value)

The copying versions toSorted, toReversed, toSpliced and with were added in ES2023 and are supported in all current browsers and Node.js 20. They replace the [...array].sort() pattern used above:

JavaScript
const sorted = lessons.toSorted((a, b) => a.minutes - b.minutes);
console.log(lessons[0].title); // → Variables (unchanged)
console.log(sorted[0].title);  // → Variables (shortest first)

"New array" means a new outer array. The objects inside are the same objects. Changing sorted[0].done also changes lessons[0].done.

A few more you will use

  • flat() flattens nested arrays one level; flatMap() maps and flattens in one go.
  • at(-1) reads the last item.
  • Array.from(nodeList) turns array-like values, such as a NodeList, into a real array.
  • join(', ') turns an array into a string.

Summary

  • map transforms, filter keeps, find returns one item, and some, every and includes answer yes or no.
  • reduce folds an array into one value; always give it a starting value.
  • Chain non-mutating methods into readable pipelines.
  • sort needs a compare function for numbers, and it changes the original; prefer toSorted.
  • Know which methods mutate, and remember that copies of arrays still share their objects.

Further reading