JavaScript Array Methods Cheat Sheet: map, filter, reduce, and Beyond
The definitive reference for JavaScript array methods. Every method explained with clear examples — from basics like push and pop to advanced patterns with reduce, flatMap, and groupBy.
Why Array Methods Matter
Arrays are the most commonly used data structure in JavaScript. Mastering array methods is the single biggest productivity boost you can give yourself as a JS developer. They replace verbose for-loops with expressive, chainable operations.
Modern JavaScript provides over 30 array methods. This guide covers every one you'll actually use, organized by what they do.
Creating Arrays
// Literal
const arr = [1, 2, 3];
// From a length
const empty = new Array(5); // [empty × 5]
const filled = Array(5).fill(0); // [0, 0, 0, 0, 0]
// From iterable
Array.from("hello"); // ["h", "e", "l", "l", "o"]
Array.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4]
// Spread
const copy = [...arr];
const merged = [...arr1, ...arr2];
// Array.of (avoids the new Array(5) trap)
Array.of(5); // [5] (not [empty × 5])
Adding and Removing Elements
push / pop — End of array
const arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4] — returns new length (4)
arr.push(5, 6); // [1, 2, 3, 4, 5, 6]
arr.pop(); // returns 6, arr is [1, 2, 3, 4, 5]
unshift / shift — Beginning of array
const arr = [1, 2, 3];
arr.unshift(0); // [0, 1, 2, 3] — returns new length (4)
arr.shift(); // returns 0, arr is [1, 2, 3]
Performance note: push/pop are O(1). unshift/shift are O(n) because they reindex every element.
splice — Add/remove at any position
const arr = [1, 2, 3, 4, 5];
// Remove 2 elements starting at index 1
arr.splice(1, 2); // returns [2, 3], arr is [1, 4, 5]
// Insert at index 1 (remove 0 elements)
arr.splice(1, 0, "a", "b"); // arr is [1, "a", "b", 4, 5]
// Replace: remove 1, insert 1
arr.splice(2, 1, "c"); // arr is [1, "a", "c", 4, 5]
toSpliced — Immutable splice (ES2023)
const arr = [1, 2, 3, 4, 5];
const newArr = arr.toSpliced(1, 2); // [1, 4, 5]
// arr is unchanged: [1, 2, 3, 4, 5]
Transforming Arrays
map — Transform every element
The most important array method. Creates a new array by applying a function to every element:
const numbers = [1, 2, 3, 4, 5];
numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
numbers.map(n => n.toString()); // ["1", "2", "3", "4", "5"]
numbers.map((n, i) => ({ index: i, value: n }));
// Real-world: transform API data
const users = [
{ id: 1, firstName: "Alice", lastName: "Smith" },
{ id: 2, firstName: "Bob", lastName: "Jones" },
];
const names = users.map(u => `${u.firstName} ${u.lastName}`);
// ["Alice Smith", "Bob Jones"]
filter — Keep elements that pass a test
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
numbers.filter(n => n > 5); // [6, 7, 8, 9, 10]
numbers.filter(n => n % 2 === 0); // [2, 4, 6, 8, 10]
// Remove falsy values
const mixed = [0, 1, "", "hello", null, undefined, false, true];
mixed.filter(Boolean); // [1, "hello", true]
// Real-world: filter active users
const activeUsers = users.filter(u => u.isActive && u.role === "admin");
reduce — Accumulate into a single value
The most powerful (and most misunderstood) array method:
const numbers = [1, 2, 3, 4, 5];
// Sum
numbers.reduce((sum, n) => sum + n, 0); // 15
// Max
numbers.reduce((max, n) => Math.max(max, n), -Infinity); // 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((groups, person) => {
const key = person.dept;
(groups[key] = groups[key] || []).push(person);
return groups;
}, {});
// Flatten nested arrays
const nested = [[1, 2], [3, 4], [5, 6]];
nested.reduce((flat, arr) => [...flat, ...arr], []); // [1, 2, 3, 4, 5, 6]
// Pipeline: chain operations
const result = [1, 2, 3, 4, 5]
.filter(n => n % 2 === 1) // [1, 3, 5]
.map(n => n * 10) // [10, 30, 50]
.reduce((sum, n) => sum + n, 0); // 90
flat / flatMap — Flatten nested arrays
const nested = [[1, 2], [3, [4, 5]]];
nested.flat(); // [1, 2, 3, [4, 5]] — one level
nested.flat(2); // [1, 2, 3, 4, 5] — two levels
nested.flat(Infinity); // [1, 2, 3, 4, 5] — all levels
// flatMap = map + flat(1) — very useful!
const sentences = ["Hello world", "Foo bar"];
sentences.flatMap(s => s.split(" ")); // ["Hello", "world", "Foo", "bar"]
// Remove empty and split
const data = ["a,b", "", "c,d,e"];
data.flatMap(s => s ? s.split(",") : []); // ["a", "b", "c", "d", "e"]
Searching and Testing
find / findIndex — First match
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
users.find(u => u.id === 2); // { id: 2, name: "Bob" }
users.find(u => u.id === 99); // undefined
users.findIndex(u => u.id === 2); // 1
users.findIndex(u => u.id === 99); // -1
findLast / findLastIndex (ES2023)
const numbers = [1, 2, 3, 4, 5, 4, 3];
numbers.findLast(n => n > 3); // 4 (last one)
numbers.findLastIndex(n => n > 3); // 5
includes / indexOf
const arr = [1, 2, 3, NaN];
arr.includes(2); // true
arr.includes(99); // false
arr.includes(NaN); // true (includes handles NaN!)
arr.indexOf(2); // 1
arr.indexOf(99); // -1
arr.indexOf(NaN); // -1 (indexOf does NOT handle NaN)
some / every — Test conditions
const numbers = [1, 2, 3, 4, 5];
numbers.some(n => n > 4); // true (at least one passes)
numbers.every(n => n > 0); // true (all pass)
numbers.every(n => n > 3); // false
Sorting
sort — In-place sort
// Alphabetical (default — converts to strings!)
["banana", "apple", "cherry"].sort(); // ["apple", "banana", "cherry"]
// DANGER: numeric sort without comparator
[10, 9, 8, 1, 2, 3].sort(); // [1, 10, 2, 3, 8, 9] — WRONG!
// Correct numeric sort
[10, 9, 8, 1, 2, 3].sort((a, b) => a - b); // [1, 2, 3, 8, 9, 10]
// Descending
[1, 2, 3].sort((a, b) => b - a); // [3, 2, 1]
// Sort objects by property
users.sort((a, b) => a.name.localeCompare(b.name));
// Sort by multiple criteria
items.sort((a, b) => {
if (a.priority !== b.priority) return a.priority - b.priority;
return a.name.localeCompare(b.name);
});
toSorted — Immutable sort (ES2023)
const arr = [3, 1, 2];
const sorted = arr.toSorted((a, b) => a - b); // [1, 2, 3]
// arr is unchanged: [3, 1, 2]
reverse / toReversed
const arr = [1, 2, 3];
arr.reverse(); // [3, 2, 1] — mutates!
arr.toReversed(); // [1, 2, 3] — immutable (ES2023)
Slicing and Joining
slice — Extract a portion (immutable)
const arr = [1, 2, 3, 4, 5];
arr.slice(1, 3); // [2, 3] (start inclusive, end exclusive)
arr.slice(2); // [3, 4, 5] (from index 2 to end)
arr.slice(-2); // [4, 5] (last 2 elements)
arr.slice(); // [1, 2, 3, 4, 5] (shallow copy)
join — Convert to string
["a", "b", "c"].join(", "); // "a, b, c"
["a", "b", "c"].join("-"); // "a-b-c"
["a", "b", "c"].join(""); // "abc"
[1, 2, 3].join(); // "1,2,3" (default: comma)
at — Access by index (supports negative)
const arr = [1, 2, 3, 4, 5];
arr.at(0); // 1
arr.at(-1); // 5 (last element!)
arr.at(-2); // 4
Iteration
forEach — Execute for each element
[1, 2, 3].forEach((value, index) => {
console.log(`${index}: ${value}`);
});
// Note: forEach returns undefined — you can't chain it
// Use map/filter/reduce for transformations instead
entries / keys / values
const arr = ["a", "b", "c"];
[...arr.entries()]; // [[0, "a"], [1, "b"], [2, "c"]]
[...arr.keys()]; // [0, 1, 2]
[...arr.values()]; // ["a", "b", "c"]
// Useful in for...of
for (const [index, value] of arr.entries()) {
console.log(`${index}: ${value}`);
}
Method Chaining Patterns
The real power of array methods comes from chaining them:
const orders = [
{ id: 1, product: "Laptop", price: 999, status: "shipped" },
{ id: 2, product: "Mouse", price: 29, status: "delivered" },
{ id: 3, product: "Keyboard", price: 79, status: "shipped" },
{ id: 4, product: "Monitor", price: 449, status: "cancelled" },
{ id: 5, product: "Headphones", price: 199, status: "delivered" },
];
// Total revenue from delivered orders
const revenue = orders
.filter(o => o.status === "delivered")
.reduce((sum, o) => sum + o.price, 0);
// 228
// Product names of shipped orders, sorted
const shippedProducts = orders
.filter(o => o.status === "shipped")
.map(o => o.product)
.sort();
// ["Keyboard", "Laptop"]
// Summary by status
const summary = orders.reduce((acc, o) => {
acc[o.status] = (acc[o.status] || 0) + o.price;
return acc;
}, {});
// { shipped: 1078, delivered: 228, cancelled: 449 }
Performance Tips
- Avoid creating intermediate arrays when processing large datasets — use a single
reduceinstead offilter().map() - Use
Setfor lookups —array.includes()is O(n),set.has()is O(1) - Use
forloops for performance-critical code — array methods have function call overhead - Prefer
some/everyoverfilterfor boolean checks — they short-circuit - Use
flatMapinstead ofmap().flat()— one pass instead of two
// Slow: O(n) lookup on every iteration
const ids = [1, 2, 3, 4, 5];
items.filter(item => ids.includes(item.id));
// Fast: O(1) lookup
const idSet = new Set(ids);
items.filter(item => idSet.has(item.id));
Quick Reference Table
| Method | Mutates? | Returns | Use For |
|---|---|---|---|
push | Yes | Length | Add to end |
pop | Yes | Removed item | Remove from end |
unshift | Yes | Length | Add to start |
shift | Yes | Removed item | Remove from start |
splice | Yes | Removed items | Add/remove anywhere |
map | No | New array | Transform elements |
filter | No | New array | Keep matching elements |
reduce | No | Any value | Accumulate |
find | No | Element or undefined | First match |
some | No | Boolean | Any match? |
every | No | Boolean | All match? |
sort | Yes | Sorted array | Sort in place |
slice | No | New array | Extract portion |
flat | No | New array | Flatten nested |
flatMap | No | New array | Map + flatten |
forEach | No | undefined | Side effects |