JavaScript Array Methods: map, filter, reduce, forEach and 15 More Explained

A practical reference for every JavaScript array method you will actually use. Each method explained with clear examples, return values, mutation behavior, and the chaining patterns that make your code cleaner.

Table of Contents
  1. Transforming: map
  2. Filtering: filter
  3. Accumulating: reduce
  4. Iterating: forEach
  5. Searching: find, findIndex, indexOf, includes
  6. Testing: some, every
  7. Sorting: sort, toSorted, reverse, toReversed
  8. Adding and Removing: push, pop, shift, unshift, splice
  9. Combining: concat, flat, flatMap, spread
  10. Creating: from, of, Array constructor, fill
  11. ES2023+ New Methods
  12. Method Chaining Patterns
  13. Performance Considerations
  14. Related Free Tools
  15. Frequently Asked Questions

Transforming: map

map() creates a new array by calling a function on every element. It does not mutate the original array. The returned array always has the same length as the original.

javascript — map examples
const numbers = [1, 2, 3, 4, 5];

// Double each number
const doubled = numbers.map(n => n * 2);
// [2, 4, 6, 8, 10]

// Extract a property from objects
const users = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "Charlie", age: 35 }
];
const names = users.map(user => user.name);
// ["Alice", "Bob", "Charlie"]

// Transform with index
const indexed = ["a", "b", "c"].map((letter, i) => `${i}: ${letter}`);
// ["0: a", "1: b", "2: c"]

// Parse strings to numbers
const strings = ["1", "2", "3"];
const nums = strings.map(Number);
// [1, 2, 3]

When working with complex transformations, you can format and minify your JavaScript with the JavaScript Minifier for production-ready output.

Filtering: filter

filter() creates a new array containing only elements that pass a test. The callback must return true to keep the element or false to exclude it.

javascript — filter examples
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Even numbers only
const evens = numbers.filter(n => n % 2 === 0);
// [2, 4, 6, 8, 10]

// Filter objects by property
const users = [
  { name: "Alice", active: true },
  { name: "Bob", active: false },
  { name: "Charlie", active: true }
];
const activeUsers = users.filter(u => u.active);
// [{ name: "Alice", active: true }, { name: "Charlie", active: true }]

// Remove falsy values (null, undefined, 0, "", false)
const messy = [0, 1, null, "hello", undefined, "", false, 42];
const clean = messy.filter(Boolean);
// [1, "hello", 42]

// Remove duplicates (simple values)
const dupes = [1, 2, 2, 3, 3, 3, 4];
const unique = dupes.filter((val, i, arr) => arr.indexOf(val) === i);
// [1, 2, 3, 4]
// Better: [...new Set(dupes)]

Accumulating: reduce

reduce() processes every element and accumulates a single result. It is the most powerful and flexible array method, capable of implementing map, filter, and nearly any other array operation.

javascript — reduce examples
const numbers = [1, 2, 3, 4, 5];

// Sum all numbers
const sum = numbers.reduce((acc, n) => acc + n, 0);
// 15

// Find maximum value
const max = numbers.reduce((a, b) => a > b ? a : b);
// 5

// Count occurrences
const fruits = ["apple", "banana", "apple", "cherry", "banana", "apple"];
const counts = fruits.reduce((acc, fruit) => {
  acc[fruit] = (acc[fruit] || 0) + 1;
  return acc;
}, {});
// { apple: 3, banana: 2, cherry: 1 }

// Group by property
const people = [
  { name: "Alice", dept: "Engineering" },
  { name: "Bob", dept: "Marketing" },
  { name: "Charlie", dept: "Engineering" }
];
const byDept = people.reduce((acc, person) => {
  const key = person.dept;
  (acc[key] = acc[key] || []).push(person);
  return acc;
}, {});

// Flatten nested arrays
const nested = [[1, 2], [3, 4], [5, 6]];
const flat = nested.reduce((acc, arr) => acc.concat(arr), []);
// [1, 2, 3, 4, 5, 6]
// Better: nested.flat()
Always Provide an Initial Value

Calling reduce() on an empty array without an initial value throws a TypeError. Always pass an initial value as the second argument: arr.reduce(fn, initialValue). This also makes the code more readable because the return type is obvious from the initial value.

Iterating: forEach

forEach() executes a function on every element but returns undefined. Use it for side effects, not for creating new arrays.

javascript — forEach examples
const items = ["apple", "banana", "cherry"];

// Log each item
items.forEach(item => console.log(item));

// Update DOM elements
document.querySelectorAll(".card").forEach(card => {
  card.classList.add("visible");
});

// forEach with index
items.forEach((item, index) => {
  console.log(`${index + 1}. ${item}`);
});
forEach vs. map

Use map() when you need the returned array. Use forEach() when you are performing side effects (logging, DOM updates, API calls). Never use map() and ignore the result — that creates an unnecessary array in memory.

javascript — Search methods
const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
  { id: 3, name: "Charlie" }
];

// find: returns first matching element (or undefined)
const bob = users.find(u => u.name === "Bob");
// { id: 2, name: "Bob" }

// findIndex: returns index of first match (or -1)
const bobIndex = users.findIndex(u => u.name === "Bob");
// 1

// findLast / findLastIndex (ES2023): search from the end
const numbers = [1, 2, 3, 2, 1];
const lastTwo = numbers.findLast(n => n === 2);    // 2 (at index 3)
const lastTwoIdx = numbers.findLastIndex(n => n === 2); // 3

// indexOf: find index of a primitive value
const colors = ["red", "green", "blue"];
colors.indexOf("green");  // 1
colors.indexOf("purple"); // -1

// includes: check if a value exists (returns boolean)
colors.includes("blue");   // true
colors.includes("yellow"); // false

Testing: some, every

javascript — Testing methods
const numbers = [2, 4, 6, 8, 10];

// every: do ALL elements pass the test?
const allEven = numbers.every(n => n % 2 === 0); // true

// some: does ANY element pass the test?
const hasLarge = numbers.some(n => n > 7); // true

// Practical: check if form is valid
const fields = [
  { name: "email", valid: true },
  { name: "password", valid: false }
];
const formValid = fields.every(f => f.valid); // false

// Practical: check if any task is overdue
const tasks = [
  { title: "Deploy", due: "2026-02-20" },
  { title: "Test", due: "2026-03-01" }
];
const hasOverdue = tasks.some(t => new Date(t.due) < new Date());

Sorting: sort, toSorted, reverse, toReversed

javascript — Sorting methods
// CAUTION: sort() MUTATES the original array
const nums = [10, 1, 21, 2];
nums.sort(); // [1, 10, 2, 21] -- lexicographic, NOT numeric!

// Numeric sort (ascending)
[10, 1, 21, 2].sort((a, b) => a - b); // [1, 2, 10, 21]

// Numeric sort (descending)
[10, 1, 21, 2].sort((a, b) => b - a); // [21, 10, 2, 1]

// Sort objects by property
const users = [
  { name: "Charlie", age: 35 },
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 }
];
users.sort((a, b) => a.age - b.age);

// Sort strings (locale-aware)
["charlie", "Alice", "bob"].sort((a, b) => a.localeCompare(b));

// NON-MUTATING alternatives (ES2023)
const original = [3, 1, 2];
const sortedCopy = original.toSorted((a, b) => a - b);
// original: [3, 1, 2] (unchanged)
// sortedCopy: [1, 2, 3]

const reversed = original.toReversed();
// original: [3, 1, 2] (unchanged)
// reversed: [2, 1, 3]

Adding and Removing: push, pop, shift, unshift, splice

These methods mutate the original array. For non-mutating alternatives, use spread syntax or toSpliced().

javascript — Mutation methods
const arr = [1, 2, 3];

arr.push(4);         // Add to end. arr = [1, 2, 3, 4]
arr.pop();           // Remove from end. Returns 4
arr.unshift(0);      // Add to beginning. arr = [0, 1, 2, 3]
arr.shift();         // Remove from beginning. Returns 0

// splice: remove/insert at any position
arr.splice(1, 1);          // Remove 1 element at index 1
arr.splice(1, 0, 2);       // Insert 2 at index 1
arr.splice(1, 1, 20, 30);  // Replace 1 element with two

// toSpliced (ES2023): non-mutating splice
const original = [1, 2, 3, 4];
const modified = original.toSpliced(1, 2, 20, 30);
// original: [1, 2, 3, 4]   (unchanged)
// modified: [1, 20, 30, 4]

Combining: concat, flat, flatMap, spread

javascript — Combining arrays
// concat: merge arrays (non-mutating)
const merged = [1, 2].concat([3, 4]);   // [1, 2, 3, 4]
const merged2 = [...[1, 2], ...[3, 4]]; // Same with spread

// flat: flatten nested arrays
[[1, 2], [3, [4, 5]]].flat();   // [1, 2, 3, [4, 5]]
[[1, 2], [3, [4, 5]]].flat(2);  // [1, 2, 3, 4, 5]
nested.flat(Infinity);            // Flatten all levels

// flatMap: map then flatten one level (single pass)
const sentences = ["Hello world", "foo bar"];
const words = sentences.flatMap(s => s.split(" "));
// ["Hello", "world", "foo", "bar"]

// Practical flatMap: expand items
const orders = [
  { id: 1, items: ["apple", "banana"] },
  { id: 2, items: ["cherry"] }
];
const allItems = orders.flatMap(o => o.items);
// ["apple", "banana", "cherry"]

Creating: from, of, Array constructor, fill

javascript — Creating arrays
// Array.from: convert iterable/array-like to array
Array.from("hello");           // ["h", "e", "l", "l", "o"]
Array.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4]
Array.from(document.querySelectorAll("div"));

// Array.of: create array from arguments
Array.of(1, 2, 3); // [1, 2, 3]
Array.of(5);        // [5] (not [undefined x 5])

// fill: fill array with a value
new Array(5).fill(0);          // [0, 0, 0, 0, 0]
[1, 2, 3, 4].fill(0, 1, 3);   // [1, 0, 0, 4]

// with (ES2023): replace one element (non-mutating)
const arr = [1, 2, 3, 4];
const updated = arr.with(2, 99);
// arr: [1, 2, 3, 4]       (unchanged)
// updated: [1, 2, 99, 4]

ES2023+ New Methods

Recent ECMAScript versions added non-mutating alternatives and new utility methods supported in all modern browsers and Node.js 20+.

javascript — Object.groupBy (ES2024)
const inventory = [
  { name: "asparagus", type: "vegetables" },
  { name: "bananas", type: "fruit" },
  { name: "cherries", type: "fruit" },
  { name: "goat", type: "meat" }
];

const grouped = Object.groupBy(inventory, item => item.type);
// {
//   vegetables: [{ name: "asparagus", ... }],
//   fruit: [{ name: "bananas", ... }, { name: "cherries", ... }],
//   meat: [{ name: "goat", ... }]
// }
Mutation Quick Reference

Mutates: push, pop, shift, unshift, splice, sort, reverse, fill. Does not mutate: map, filter, reduce, concat, flat, flatMap, slice, toSorted, toReversed, toSpliced, with. When in doubt, prefer non-mutating methods to avoid side-effect bugs.

Method Chaining Patterns

Because map, filter, and other methods return arrays, you can chain them into data processing pipelines:

javascript — Chaining patterns
const transactions = [
  { id: 1, amount: 50, type: "income" },
  { id: 2, amount: 30, type: "expense" },
  { id: 3, amount: 100, type: "income" },
  { id: 4, amount: 20, type: "expense" },
  { id: 5, amount: 200, type: "income" }
];

// Pipeline: filter -> map -> reduce
const totalIncome = transactions
  .filter(t => t.type === "income")
  .map(t => t.amount)
  .reduce((sum, amount) => sum + amount, 0);
// 350

// Get sorted, formatted list of expensive items
const products = [
  { name: "Laptop", price: 999 },
  { name: "Mouse", price: 29 },
  { name: "Monitor", price: 499 },
  { name: "Keyboard", price: 79 }
];

const expensiveFormatted = products
  .filter(p => p.price > 50)
  .toSorted((a, b) => b.price - a.price)
  .map(p => `${p.name}: $${p.price}`);
// ["Laptop: $999", "Monitor: $499", "Keyboard: $79"]

Performance Considerations


Related Free Tools


Frequently Asked Questions

map() creates and returns a new array with the results of calling a function on every element. forEach() executes a function on every element but returns undefined. Use map() when you need to transform data and use the resulting array. Use forEach() when you want to perform side effects like logging, updating the DOM, or making API calls for each element. Because map() returns a new array, you can chain it with other array methods like filter() and reduce(). forEach() cannot be chained since it returns undefined.

reduce() iterates over an array and accumulates a single result value. It takes two arguments: a callback function and an optional initial value. The callback receives four parameters: the accumulator (the running total or accumulated result), the current element, the current index, and the original array. On each iteration, the callback's return value becomes the new accumulator for the next iteration. Always provide an initial value to avoid unexpected behavior with empty arrays. Common uses include summing numbers (reduce((sum, n) => sum + n, 0)), flattening arrays, counting occurrences, and grouping objects by a property.

Yes, Array.sort() mutates the original array in place and also returns the sorted array. This is a common source of bugs. If you need to sort without modifying the original, create a copy first using the spread operator ([...arr].sort()), Array.from(arr).sort(), or arr.slice().sort(). As of ES2023, you can use the new toSorted() method which returns a sorted copy without mutating the original. Also note that sort() without a compare function converts elements to strings and sorts them lexicographically, which means [10, 9, 80].sort() produces [10, 80, 9]. Always pass a compare function for numbers: arr.sort((a, b) => a - b).

find() returns the first element that matches a condition, or undefined if no match is found. It stops searching as soon as it finds a match. filter() returns a new array containing all elements that match a condition, or an empty array if nothing matches. Use find() when you expect one result and want to stop early, like looking up a user by ID. Use filter() when you want all matching results, like getting all users in a specific city. find() is more efficient when you only need one result because it does not process the remaining elements after finding a match.

ES2023 introduced non-mutating versions of existing methods: toSorted() (like sort() but returns a new array), toReversed() (like reverse() but non-mutating), toSpliced() (like splice() but non-mutating), and with(index, value) which returns a new array with one element replaced. These are supported in all modern browsers. ES2024 added Object.groupBy(array, callback) which groups array elements by a key returned by the callback function, replacing the common reduce-based grouping pattern. It returns a null-prototype object with arrays as values.

NT

QTool

We build free, browser-based developer tools. 269 tool pages for JavaScript, web development, and everyday coding. All client-side, no signup required.

269 Developer Tools, Zero Signup

Browse 269 indexed tool pages with no QTool account required, and inspect the source on GitHub.

Browse Free Tools Read More Articles

Related Articles

Built by Miguel

Need a custom tool or website?

From . Delivered in 24-48h. You own the code.

View Services →