Master every JavaScript array method — map, filter, reduce, find, flat, and more — with practical examples and performance tips.
JavaScript arrays come with a rich set of built-in methods. Knowing which method to use — and when — separates junior developers from senior ones. This is the complete reference.
const prices = [10, 20, 30];
const withTax = prices.map(p => p * 1.2); // [12, 24, 36]
// Object transformation
const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
const names = users.map(u => u.name); // ['Alice', 'Bob']
const ids = users.map(({ id }) => id); // [1, 2]
const nums = [1, 2, 3, 4, 5, 6];
const evens = nums.filter(n => n % 2 === 0); // [2, 4, 6]
const active = users.filter(u => u.isActive);
// Remove falsy values
const clean = [0, 1, null, 2, undefined, 3].filter(Boolean); // [1, 2, 3]
const sum = [1, 2, 3, 4].reduce((acc, n) => acc + n, 0); // 10
// Group by
const people = [
{ name: 'Alice', dept: 'eng' },
{ name: 'Bob', dept: 'eng' },
{ name: 'Carol', dept: 'design' },
];
const byDept = people.reduce((acc, p) => {
(acc[p.dept] ??= []).push(p);
return acc;
}, {});
// { eng: [{Alice}, {Bob}], design: [{Carol}] }
// Count occurrences
const fruits = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple'];
const counts = fruits.reduce((acc, f) => ({ ...acc, [f]: (acc[f] ?? 0) + 1 }), {});
// { apple: 3, banana: 2, cherry: 1 }
const sentences = ['Hello world', 'foo bar baz'];
const words = sentences.flatMap(s => s.split(' '));
// ['Hello', 'world', 'foo', 'bar', 'baz']
// Remove and expand in one step
const data = [1, [2, 3], 4, [5, 6]];
// flat()
data.flat(); // [1, 2, 3, 4, 5, 6]
// flat(Infinity) for deeply nested
[1, [2, [3, [4]]]].flat(Infinity); // [1, 2, 3, 4]
const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
const alice = users.find(u => u.id === 1); // { id: 1, name: 'Alice' }
const idx = users.findIndex(u => u.id === 1); // 0
// findLast / findLastIndex (ES2023)
const last = users.findLast(u => u.name.length > 3); // { id: 2, name: 'Alice' } no wait
const ages = [18, 24, 16, 30];
ages.some(a => a < 18); // true — at least one is under 18
ages.every(a => a >= 18); // false — not all are 18+
// Check if array is non-empty and all valid
const allValid = arr.length > 0 && arr.every(item => item != null);
[1, 2, 3].includes(2); // true
['a', 'b', 'c'].indexOf('b'); // 1
['a', 'b', 'c'].lastIndexOf('b'); // 1
// Note: includes uses SameValueZero (handles NaN)
[NaN].includes(NaN); // true
[NaN].indexOf(NaN); // -1 (doesn't work!)
// Sort strings
['banana', 'apple', 'cherry'].sort(); // ['apple', 'banana', 'cherry']
// Sort numbers (MUST provide comparator!)
[10, 1, 21, 2].sort((a, b) => a - b); // [1, 2, 10, 21] ascending
[10, 1, 21, 2].sort((a, b) => b - a); // [21, 10, 2, 1] descending
// Sort objects by property
users.sort((a, b) => a.name.localeCompare(b.name));
users.sort((a, b) => a.createdAt - b.createdAt);
// toSorted() — non-mutating (ES2023)
const sorted = original.toSorted((a, b) => a - b);
// Reverse
[1, 2, 3].reverse(); // [3, 2, 1] — mutates!
[1, 2, 3].toReversed(); // [3, 2, 1] — non-mutating (ES2023)
const arr = [1, 2, 3];
// End
arr.push(4); // arr = [1,2,3,4]
arr.pop(); // returns 4, arr = [1,2,3]
// Start
arr.unshift(0); // arr = [0,1,2,3]
arr.shift(); // returns 0, arr = [1,2,3]
// Anywhere with splice (mutates!)
arr.splice(1, 0, 'a'); // insert 'a' at index 1
arr.splice(1, 1); // remove 1 element at index 1
arr.splice(1, 2, 'x'); // replace 2 elements at index 1 with 'x'
// Non-mutating alternatives (ES2023)
arr.with(1, 'x'); // replace index 1 with 'x'
arr.toSpliced(1, 1); // remove 1 element at index 1
// Join arrays
[1,2].concat([3,4], [5,6]); // [1,2,3,4,5,6]
[...[1,2], ...[3,4]]; // [1,2,3,4] — spread (preferred)
// Slice (non-mutating)
[1,2,3,4,5].slice(1, 3); // [2, 3]
[1,2,3,4,5].slice(-2); // [4, 5] (last 2)
// Join elements to string
[1, 2, 3].join(', '); // '1, 2, 3'
[1, 2, 3].join(''); // '123'
// From an iterable
Array.from('hello'); // ['h','e','l','l','o']
Array.from({length: 5}, (_, i) => i); // [0,1,2,3,4]
Array.from(new Set([1,2,2,3])); // [1,2,3]
// Fill
new Array(5).fill(0); // [0,0,0,0,0]
[1,2,3].fill(0, 1, 3); // [1,0,0]
// Array.of
Array.of(1, 2, 3); // [1, 2, 3]
indexOf in loops — use a Set or Map for O(1) lookups instead of O(n) searchpush vs spread — arr.push(...items) is faster than arr = [...arr, ...items] for large arraysfor loop beats forEach — by ~10–30% for tight computation loopsfilter().map() vs single reduce() — two passes vs one; for large arrays, reduce wins; for readability, chaining winsflat(Infinity) is slow — implement your own recursive flatten for known depths