JavaScript Array Methods: The Complete Guide
Arrays are the most commonly used data structure in JavaScript. Whether you are building a REST API, rendering a UI, or processing data, you will reach for array methods dozens of times a day. Yet most developers only use a handful of them and miss the ones that could make their code shorter, clearer, and faster.
This JavaScript array tutorial covers every method you need to know in 2026, from the basics like push and pop to powerful transformations with map, filter, and reduce. Each section includes practical code examples you can copy and use immediately. By the end, you will have a complete mental model of the js array API and know exactly which method to reach for in any situation.
1. Creating Arrays
Before you can transform data, you need to create arrays. JavaScript gives you several ways to do this, each suited to different situations.
Array Literals
The most common and readable way to create an array:
const fruits = ['apple', 'banana', 'cherry'];
const numbers = [1, 2, 3, 4, 5];
const mixed = ['hello', 42, true, null, { name: 'Dev' }];
const empty = [];
Array.from()
Array.from() creates an array from any iterable or array-like object. This is invaluable for converting NodeLists, strings, Sets, Maps, and generator results into real arrays.
// From a string — splits into individual characters
Array.from('hello');
// ['h', 'e', 'l', 'l', 'o']
// From a Set — easy way to deduplicate
Array.from(new Set([1, 2, 2, 3, 3]));
// [1, 2, 3]
// From a NodeList (DOM elements)
Array.from(document.querySelectorAll('.card'));
// With a mapping function (second argument)
Array.from({ length: 5 }, (_, i) => i * 2);
// [0, 2, 4, 6, 8]
// Generate a range of numbers
Array.from({ length: 10 }, (_, i) => i + 1);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Array.of()
Array.of() creates an array from its arguments. It exists to fix a quirk of the Array() constructor, which behaves differently when passed a single number.
// The problem with Array()
Array(3); // [empty x 3] — creates sparse array with 3 empty slots
Array(3, 4); // [3, 4] — creates array with two elements
// Array.of() is consistent
Array.of(3); // [3] — always creates array with the given elements
Array.of(3, 4); // [3, 4]
Array.of(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
Spread Operator
The spread operator ... is the most versatile way to create arrays from existing data:
// Clone an array (shallow copy)
const original = [1, 2, 3];
const clone = [...original];
// Merge multiple arrays
const a = [1, 2];
const b = [3, 4];
const c = [5, 6];
const merged = [...a, ...b, ...c];
// [1, 2, 3, 4, 5, 6]
// Convert iterables
const chars = [... 'hello']; // ['h', 'e', 'l', 'l', 'o']
const unique = [...new Set([1, 1, 2, 3, 3])]; // [1, 2, 3]
// Insert elements at a specific position
const items = [1, 2, 5, 6];
const withInsert = [...items.slice(0, 2), 3, 4, ...items.slice(2)];
// [1, 2, 3, 4, 5, 6]
2. Adding and Removing Elements
These methods mutate the original array. That is important to remember when working with shared state or reactive frameworks where mutations can cause unexpected side effects.
push() and pop() — End of Array
const stack = [1, 2, 3];
// push() adds to the end, returns new length
stack.push(4); // returns 4, stack is [1, 2, 3, 4]
stack.push(5, 6); // returns 6, stack is [1, 2, 3, 4, 5, 6]
// pop() removes from the end, returns removed element
stack.pop(); // returns 6, stack is [1, 2, 3, 4, 5]
stack.pop(); // returns 5, stack is [1, 2, 3, 4]
unshift() and shift() — Start of Array
const queue = [3, 4, 5];
// unshift() adds to the beginning, returns new length
queue.unshift(1, 2); // returns 5, queue is [1, 2, 3, 4, 5]
// shift() removes from the beginning, returns removed element
queue.shift(); // returns 1, queue is [2, 3, 4, 5]
Performance note: push() and pop() are O(1) operations. unshift() and shift() are O(n) because every element must be re-indexed. For large arrays, if you frequently add or remove from the front, consider using a different data structure or reversing your approach.
splice() — The Swiss Army Knife
splice() can insert, remove, or replace elements at any position. It mutates the array and returns an array of removed elements.
const arr = ['a', 'b', 'c', 'd', 'e'];
// Remove 2 elements starting at index 1
arr.splice(1, 2);
// returns ['b', 'c'], arr is ['a', 'd', 'e']
// Insert without removing (deleteCount = 0)
arr.splice(1, 0, 'x', 'y');
// returns [], arr is ['a', 'x', 'y', 'd', 'e']
// Replace: remove 1 element at index 2, insert 'z'
arr.splice(2, 1, 'z');
// returns ['y'], arr is ['a', 'x', 'z', 'd', 'e']
// Remove from the end using negative index
arr.splice(-1, 1);
// returns ['e'], arr is ['a', 'x', 'z', 'd']
Immutable Alternatives (ES2023+)
Modern JavaScript provides immutable counterparts that return new arrays instead of mutating the original. These are ideal for state management in frameworks like React:
const arr = [3, 1, 4, 1, 5];
// toSorted() — returns a new sorted array
const sorted = arr.toSorted((a, b) => a - b);
// sorted is [1, 1, 3, 4, 5], arr is unchanged
// toReversed() — returns a new reversed array
const reversed = arr.toReversed();
// reversed is [5, 1, 4, 1, 3], arr is unchanged
// toSpliced() — returns a new array with splice applied
const spliced = arr.toSpliced(1, 2, 'a', 'b');
// spliced is [3, 'a', 'b', 1, 5], arr is unchanged
// with() — returns a new array with one element replaced
const replaced = arr.with(0, 99);
// replaced is [99, 1, 4, 1, 5], arr is unchanged
3. Transforming Arrays
Transformation methods are the heart of modern JavaScript. They let you express data processing as a pipeline of operations, making your code declarative and easy to reason about. These are the javascript array methods you will use most often.
map() — Transform Every Element
map() creates a new array by calling a function on every element. It does not mutate the original. This is the most fundamental transformation method.
const numbers = [1, 2, 3, 4, 5];
// Double every 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 data for an API response
const apiResponse = users.map(({ name, age }) => ({
displayName: name.toUpperCase(),
isAdult: age >= 18,
category: age < 30 ? 'young' : 'experienced'
}));
// Index is available as second argument
const indexed = ['a', 'b', 'c'].map((item, i) => `${i}: ${item}`);
// ['0: a', '1: b', '2: c']
filter() — Select Matching Elements
filter() creates a new array containing only the elements where the callback returns a truthy value.
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Keep only even numbers
const evens = numbers.filter(n => n % 2 === 0);
// [2, 4, 6, 8, 10]
// Filter objects by a condition
const products = [
{ name: 'Laptop', price: 999, inStock: true },
{ name: 'Phone', price: 699, inStock: false },
{ name: 'Tablet', price: 449, inStock: true },
{ name: 'Watch', price: 299, inStock: true }
];
const affordable = products.filter(p => p.price < 500 && p.inStock);
// [{ name: 'Tablet', ... }, { name: 'Watch', ... }]
// Remove falsy values from an array
const messy = [0, 'hello', '', null, 42, undefined, false, 'world'];
const clean = messy.filter(Boolean);
// ['hello', 42, 'world']
// Remove duplicates (for simple values, prefer Set)
const withDupes = [1, 2, 2, 3, 3, 4];
const unique = withDupes.filter((v, i, arr) => arr.indexOf(v) === i);
// [1, 2, 3, 4]
reduce() — Accumulate Into Any Shape
reduce() is the most powerful array method. It processes every element and accumulates the results into a single value, which can be a number, string, object, array, or anything else. Understanding map, filter, and reduce is essential for working with data in JavaScript.
const numbers = [1, 2, 3, 4, 5];
// Sum all numbers
const sum = numbers.reduce((acc, n) => acc + n, 0);
// 15
// Find the maximum value
const max = numbers.reduce((a, b) => a > b ? a : b);
// 5
// Count occurrences of each value
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 objects by a property
const people = [
{ name: 'Alice', dept: 'Engineering' },
{ name: 'Bob', dept: 'Marketing' },
{ name: 'Charlie', dept: 'Engineering' },
{ name: 'Diana', dept: 'Marketing' },
{ name: 'Eve', dept: 'Engineering' }
];
const byDept = people.reduce((groups, person) => {
const key = person.dept;
(groups[key] = groups[key] || []).push(person);
return groups;
}, {});
// { Engineering: [Alice, Charlie, Eve], Marketing: [Bob, Diana] }
// Flatten a 2D array into 1D (prefer flat() for this)
const matrix = [[1, 2], [3, 4], [5, 6]];
const flat = matrix.reduce((acc, row) => [...acc, ...row], []);
// [1, 2, 3, 4, 5, 6]
// Build a lookup map from an array of objects
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const userMap = users.reduce((map, user) => {
map[user.id] = user;
return map;
}, {});
// { 1: { id: 1, name: 'Alice' }, 2: { ... }, 3: { ... } }
flat() and flatMap()
flat() creates a new array with sub-array elements concatenated to a specified depth. flatMap() combines map() and flat(1) in a single pass, which is more efficient.
// flat() — flatten nested arrays
const nested = [1, [2, 3], [4, [5, 6]]];
nested.flat(); // [1, 2, 3, 4, [5, 6]] — default depth is 1
nested.flat(2); // [1, 2, 3, 4, 5, 6] — depth 2
nested.flat(Infinity); // flattens all levels
// flatMap() — map then flatten by 1 level
const sentences = ['Hello world', 'Goodbye moon'];
const words = sentences.flatMap(s => s.split(' '));
// ['Hello', 'world', 'Goodbye', 'moon']
// flatMap is great for one-to-many transformations
const orders = [
{ id: 1, items: ['apple', 'banana'] },
{ id: 2, items: ['cherry'] },
{ id: 3, items: ['date', 'elderberry', 'fig'] }
];
const allItems = orders.flatMap(order => order.items);
// ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig']
// Use flatMap to filter and transform in one step
const nums = [1, 2, 3, 4, 5, 6];
const doubledEvens = nums.flatMap(n => n % 2 === 0 ? [n * 2] : []);
// [4, 8, 12] — filter + map in a single pass
sort()
sort() sorts the array in place and returns the sorted array. Without a comparator, it converts elements to strings and sorts lexicographically, which is almost never what you want for numbers.
// WARNING: default sort is lexicographic
[10, 9, 80, 1, 21].sort();
// [1, 10, 21, 80, 9] — wrong for numbers!
// Always provide a comparator for numbers
[10, 9, 80, 1, 21].sort((a, b) => a - b);
// [1, 9, 10, 21, 80] — ascending
[10, 9, 80, 1, 21].sort((a, b) => b - a);
// [80, 21, 10, 9, 1] — descending
// Sort strings case-insensitively
const names = ['Charlie', 'alice', 'Bob', 'diana'];
names.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }));
// ['alice', 'Bob', 'Charlie', 'diana']
// Sort objects by a property
const tasks = [
{ title: 'Deploy', priority: 1 },
{ title: 'Test', priority: 2 },
{ title: 'Fix bug', priority: 1 },
{ title: 'Review', priority: 3 }
];
tasks.sort((a, b) => a.priority - b.priority);
// Stable sort: elements with equal keys keep original order
// This is guaranteed in all modern engines since ES2019
reverse()
reverse() reverses the array in place. Use toReversed() if you need an immutable version.
const arr = [1, 2, 3, 4, 5];
arr.reverse(); // [5, 4, 3, 2, 1] — mutates arr
// Immutable alternative
const original = [1, 2, 3, 4, 5];
const reversed = original.toReversed(); // [5, 4, 3, 2, 1]
// original is still [1, 2, 3, 4, 5]
// Reverse a string
const str = 'hello';
const reversedStr = [...str].reverse().join('');
// 'olleh'
slice() — Extract a Portion
slice() returns a shallow copy of a portion of the array. It does not mutate the original. Do not confuse it with splice().
const arr = ['a', 'b', 'c', 'd', 'e'];
arr.slice(1, 3); // ['b', 'c'] — from index 1 up to (not including) 3
arr.slice(2); // ['c', 'd', 'e'] — from index 2 to end
arr.slice(-2); // ['d', 'e'] — last 2 elements
arr.slice(0, -1); // ['a', 'b', 'c', 'd'] — everything except last
arr.slice(); // ['a', 'b', 'c', 'd', 'e'] — shallow clone
4. Searching and Testing
These methods help you find elements and check conditions. They make your code more expressive than manual loops.
find() and findIndex()
find() returns the first element that satisfies the callback. findIndex() returns its index. Both return undefined or -1 respectively when nothing is found.
const users = [
{ id: 1, name: 'Alice', role: 'admin' },
{ id: 2, name: 'Bob', role: 'user' },
{ id: 3, name: 'Charlie', role: 'user' },
{ id: 4, name: 'Diana', role: 'admin' }
];
// Find the first admin
const admin = users.find(u => u.role === 'admin');
// { id: 1, name: 'Alice', role: 'admin' }
// Find the index of Bob
const bobIndex = users.findIndex(u => u.name === 'Bob');
// 1
// Returns undefined / -1 when not found
users.find(u => u.name === 'Unknown'); // undefined
users.findIndex(u => u.name === 'Unknown'); // -1
// findLast() and findLastIndex() — search from the end (ES2023)
const lastAdmin = users.findLast(u => u.role === 'admin');
// { id: 4, name: 'Diana', role: 'admin' }
const lastAdminIndex = users.findLastIndex(u => u.role === 'admin');
// 3
indexOf() and lastIndexOf()
These search for a value using strict equality (===). They work best with primitives.
const colors = ['red', 'blue', 'green', 'blue', 'red'];
colors.indexOf('blue'); // 1 — first occurrence
colors.lastIndexOf('blue'); // 3 — last occurrence
colors.indexOf('purple'); // -1 — not found
// Search starting from a specific index
colors.indexOf('blue', 2); // 3 — starts searching from index 2
// Common pattern: check if element exists
if (colors.indexOf('green') !== -1) {
console.log('Found green');
}
// Prefer includes() for this — see below
includes()
includes() returns true or false. It is cleaner and more readable than indexOf() !== -1. Unlike indexOf(), it correctly handles NaN.
const arr = [1, 2, 3, NaN, undefined];
arr.includes(2); // true
arr.includes(4); // false
arr.includes(NaN); // true — indexOf would return -1!
arr.includes(undefined); // true
// Check from a starting index
arr.includes(1, 1); // false — starts checking from index 1
// Practical example: validate user input
const validRoles = ['admin', 'editor', 'viewer'];
function isValidRole(role) {
return validRoles.includes(role);
}
isValidRole('admin'); // true
isValidRole('hacker'); // false
some() and every()
some() returns true if at least one element passes the test. every() returns true if all elements pass. Both short-circuit: some() stops at the first true, every() stops at the first false.
const numbers = [2, 4, 6, 7, 8, 10];
// Does the array contain any odd numbers?
numbers.some(n => n % 2 !== 0); // true (7 is odd)
// Are all numbers positive?
numbers.every(n => n > 0); // true
// Practical: check if a form is valid
const fields = [
{ name: 'email', valid: true },
{ name: 'password', valid: true },
{ name: 'age', valid: false }
];
const allValid = fields.every(f => f.valid); // false
const anyInvalid = fields.some(f => !f.valid); // true
// some() on an empty array returns false
[].some(x => x > 0); // false
// every() on an empty array returns true (vacuous truth)
[].every(x => x > 0); // true
5. Iterating Over Arrays
JavaScript provides multiple ways to iterate. Choose based on whether you need to transform data, perform side effects, or control the loop flow.
forEach()
forEach() executes a function for each element. It does not return a value (always returns undefined). Use it for side effects, not transformations.
const fruits = ['apple', 'banana', 'cherry'];
// Basic iteration
fruits.forEach(fruit => {
console.log(fruit);
});
// With index and array
fruits.forEach((fruit, index, arr) => {
console.log(`${index + 1}/${arr.length}: ${fruit}`);
});
// IMPORTANT: you cannot break out of forEach
// If you need early termination, use for...of or a regular for loop
// This will NOT work as expected:
fruits.forEach(fruit => {
if (fruit === 'banana') return; // only skips THIS iteration
console.log(fruit); // prints 'apple', then 'cherry'
});
for...of
for...of is the modern way to iterate when you need break, continue, or await inside the loop.
const items = ['alpha', 'beta', 'gamma', 'delta'];
// Basic iteration
for (const item of items) {
console.log(item);
}
// Break early
for (const item of items) {
if (item === 'gamma') break;
console.log(item); // 'alpha', 'beta'
}
// Works with async/await
async function processItems(urls) {
for (const url of urls) {
const response = await fetch(url);
const data = await response.json();
console.log(data);
}
}
entries(), keys(), and values()
These methods return iterators, which are useful with for...of when you need indices alongside values.
const colors = ['red', 'green', 'blue'];
// entries() gives [index, value] pairs
for (const [index, color] of colors.entries()) {
console.log(`${index}: ${color}`);
}
// 0: red
// 1: green
// 2: blue
// keys() gives indices only
for (const index of colors.keys()) {
console.log(index); // 0, 1, 2
}
// values() gives values only (same as for...of directly)
for (const color of colors.values()) {
console.log(color); // red, green, blue
}
// Convert to array of entries
const entryArray = [...colors.entries()];
// [[0, 'red'], [1, 'green'], [2, 'blue']]
6. Combining and Joining Arrays
concat()
concat() merges two or more arrays into a new array without mutating the originals.
const a = [1, 2];
const b = [3, 4];
const c = [5, 6];
const merged = a.concat(b, c);
// [1, 2, 3, 4, 5, 6]
// concat also accepts individual values
a.concat(3, 4, [5, 6]);
// [1, 2, 3, 4, 5, 6]
// Spread is the modern alternative and usually clearer
const merged2 = [...a, ...b, ...c];
// [1, 2, 3, 4, 5, 6]
join()
join() combines all elements into a string with a separator. The default separator is a comma.
const words = ['JavaScript', 'Array', 'Methods'];
words.join(' '); // 'JavaScript Array Methods'
words.join('-'); // 'JavaScript-Array-Methods'
words.join(', '); // 'JavaScript, Array, Methods'
words.join(''); // 'JavaScriptArrayMethods'
// Practical: build a CSV row
const row = ['Alice', 30, 'Engineering', 'alice@example.com'];
const csv = row.join(',');
// 'Alice,30,Engineering,alice@example.com'
// Practical: build a file path
const parts = ['home', 'user', 'documents', 'file.txt'];
const path = '/' + parts.join('/');
// '/home/user/documents/file.txt'
// Practical: format a list with proper grammar
function formatList(items) {
if (items.length <= 1) return items.join('');
const last = items.at(-1);
const rest = items.slice(0, -1);
return `${rest.join(', ')} and ${last}`;
}
formatList(['Alice', 'Bob', 'Charlie']);
// 'Alice, Bob and Charlie'
Spread Operator for Combining
// Prepend or append elements
const base = [2, 3, 4];
const withBookends = [1, ...base, 5];
// [1, 2, 3, 4, 5]
// Merge and deduplicate
const arr1 = [1, 2, 3];
const arr2 = [3, 4, 5];
const uniqueMerge = [...new Set([...arr1, ...arr2])];
// [1, 2, 3, 4, 5]
// Combine with conditional elements
const features = [
'core',
...(isPremium ? ['analytics', 'export'] : []),
...(isAdmin ? ['admin-panel'] : []),
'help'
];
7. Common Patterns and Recipes
These are the real-world patterns that experienced developers reach for daily. Each one combines the javascript array methods covered above into practical solutions.
Deduplicate an Array
// Simple values — use Set
const nums = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(nums)];
// [1, 2, 3, 4]
// Objects — deduplicate by a key
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice (duplicate)' }
];
const uniqueById = users.filter((user, index, self) =>
index === self.findIndex(u => u.id === user.id)
);
// [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
// Using Map for better performance on large arrays
const uniqueUsers = [...new Map(users.map(u => [u.id, u])).values()];
// keeps the LAST occurrence of each id
Group By
// Using Object.groupBy() — ES2024
const inventory = [
{ name: 'Apples', type: 'fruit', quantity: 5 },
{ name: 'Bananas', type: 'fruit', quantity: 12 },
{ name: 'Carrots', type: 'vegetable', quantity: 8 },
{ name: 'Peas', type: 'vegetable', quantity: 3 }
];
const grouped = Object.groupBy(inventory, item => item.type);
// {
// fruit: [{ name: 'Apples', ... }, { name: 'Bananas', ... }],
// vegetable: [{ name: 'Carrots', ... }, { name: 'Peas', ... }]
// }
// If Object.groupBy is not available, use reduce
function groupBy(arr, keyFn) {
return arr.reduce((groups, item) => {
const key = keyFn(item);
(groups[key] = groups[key] || []).push(item);
return groups;
}, {});
}
const grouped2 = groupBy(inventory, item => item.type);
Chunk an Array
// Split an array into smaller arrays of a given size
function chunk(arr, size) {
const chunks = [];
for (let i = 0; i < arr.length; i += size) {
chunks.push(arr.slice(i, i + size));
}
return chunks;
}
chunk([1, 2, 3, 4, 5, 6, 7], 3);
// [[1, 2, 3], [4, 5, 6], [7]]
// Functional version using Array.from
function chunkFn(arr, size) {
return Array.from(
{ length: Math.ceil(arr.length / size) },
(_, i) => arr.slice(i * size, i * size + size)
);
}
// Practical: batch API requests
async function batchProcess(items, batchSize, processFn) {
const batches = chunk(items, batchSize);
for (const batch of batches) {
await Promise.all(batch.map(processFn));
console.log(`Processed batch of ${batch.length} items`);
}
}
Partition an Array
// Split an array into two groups based on a condition
function partition(arr, predicate) {
return arr.reduce(
([pass, fail], item) => {
return predicate(item)
? [[...pass, item], fail]
: [pass, [...fail, item]];
},
[[], []]
);
}
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const [evens, odds] = partition(numbers, n => n % 2 === 0);
// evens: [2, 4, 6, 8, 10]
// odds: [1, 3, 5, 7, 9]
// Practical: separate valid from invalid entries
const [valid, invalid] = partition(formData, field => field.isValid);
Zip Arrays Together
// Combine corresponding elements from multiple arrays
function zip(...arrays) {
const minLength = Math.min(...arrays.map(a => a.length));
return Array.from({ length: minLength }, (_, i) =>
arrays.map(a => a[i])
);
}
const names = ['Alice', 'Bob', 'Charlie'];
const ages = [30, 25, 35];
const roles = ['admin', 'user', 'user'];
const zipped = zip(names, ages, roles);
// [['Alice', 30, 'admin'], ['Bob', 25, 'user'], ['Charlie', 35, 'user']]
// Convert to objects
const users = zip(names, ages, roles).map(([name, age, role]) => ({
name, age, role
}));
Sum, Average, Min, Max
const values = [4, 8, 15, 16, 23, 42];
const sum = values.reduce((a, b) => a + b, 0); // 108
const avg = sum / values.length; // 18
const min = Math.min(...values); // 4
const max = Math.max(...values); // 42
// WARNING: Math.min/max with spread can cause stack overflow
// on very large arrays (100,000+ elements). Use reduce instead:
const safeMax = values.reduce((a, b) => Math.max(a, b), -Infinity);
const safeMin = values.reduce((a, b) => Math.min(a, b), Infinity);
Pipe Transformations
// Chain map, filter, reduce for clean data pipelines
const orders = [
{ product: 'Laptop', price: 999, quantity: 2, status: 'shipped' },
{ product: 'Phone', price: 699, quantity: 1, status: 'cancelled' },
{ product: 'Tablet', price: 449, quantity: 3, status: 'shipped' },
{ product: 'Watch', price: 299, quantity: 1, status: 'shipped' },
{ product: 'Headphones', price: 149, quantity: 5, status: 'processing' }
];
// Total revenue from shipped orders
const shippedRevenue = orders
.filter(o => o.status === 'shipped')
.map(o => o.price * o.quantity)
.reduce((sum, revenue) => sum + revenue, 0);
// 999*2 + 449*3 + 299*1 = 1998 + 1347 + 299 = 3644
// Top 3 most expensive items (by line total)
const topItems = orders
.map(o => ({ ...o, total: o.price * o.quantity }))
.sort((a, b) => b.total - a.total)
.slice(0, 3)
.map(o => `${o.product}: $${o.total}`);
// ['Laptop: $1998', 'Tablet: $1347', 'Headphones: $745']
Create a Lookup Object from an Array
// Convert an array of objects into a keyed object for O(1) lookups
const products = [
{ sku: 'A100', name: 'Widget', price: 9.99 },
{ sku: 'B200', name: 'Gadget', price: 24.99 },
{ sku: 'C300', name: 'Doohickey', price: 14.99 }
];
// Using Object.fromEntries + map
const bySku = Object.fromEntries(
products.map(p => [p.sku, p])
);
// { A100: { sku: 'A100', ... }, B200: { ... }, C300: { ... } }
// Now access in O(1) instead of searching
bySku['B200'].price; // 24.99
8. Performance Considerations
Choosing the right javascript array methods is not just about readability. In hot paths and large datasets, the difference between approaches can mean milliseconds or megabytes.
Avoid Chaining When Arrays Are Large
// BAD: creates 3 intermediate arrays
const result = hugeArray
.filter(x => x.active)
.map(x => x.value)
.reduce((sum, v) => sum + v, 0);
// BETTER: single pass with reduce
const result2 = hugeArray.reduce((sum, x) => {
return x.active ? sum + x.value : sum;
}, 0);
// For arrays under ~10,000 elements, chaining is fine.
// Optimize only when profiling shows it matters.
Mutating vs. Non-Mutating
// sort() mutates — this can cause bugs in shared state
const original = [3, 1, 4, 1, 5];
const sorted = original.sort((a, b) => a - b);
// original is now [1, 1, 3, 4, 5] — mutated!
// sorted === original — they are the SAME reference
// Fix: copy first
const safeSorted = [...original].sort((a, b) => a - b);
// or use toSorted() in modern environments
const safeSorted2 = original.toSorted((a, b) => a - b);
Use the Right Data Structure
// includes() on an array is O(n) — slow for frequent lookups
const allowedIds = [1, 5, 12, 38, 99, 204, 567];
items.filter(item => allowedIds.includes(item.id)); // O(n*m)
// Convert to Set for O(1) lookups
const allowedSet = new Set(allowedIds);
items.filter(item => allowedSet.has(item.id)); // O(n)
// Use Map instead of find() when you repeatedly search by key
const userArray = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
// Slow: O(n) each time
userArray.find(u => u.id === targetId);
// Fast: O(1) after initial build
const userMap = new Map(userArray.map(u => [u.id, u]));
userMap.get(targetId);
Preallocate When Size Is Known
// Building arrays one element at a time can cause repeated resizing.
// When you know the final size, Array.from is efficient:
// Instead of:
const result = [];
for (let i = 0; i < 100000; i++) {
result.push(computeValue(i));
}
// Prefer:
const result2 = Array.from({ length: 100000 }, (_, i) => computeValue(i));
Watch Out for Accidental O(n^2)
// This innocent-looking code is O(n^2)
const unique = arr.filter((v, i, self) => self.indexOf(v) === i);
// indexOf scans from the start for EVERY element
// Fix: use Set — O(n)
const unique2 = [...new Set(arr)];
// Another trap: nested find/includes in a loop
orders.forEach(order => {
const customer = customers.find(c => c.id === order.customerId);
// If orders has 10,000 items and customers has 5,000,
// this does up to 50,000,000 comparisons
});
// Fix: build a lookup map first
const customerMap = new Map(customers.map(c => [c.id, c]));
orders.forEach(order => {
const customer = customerMap.get(order.customerId); // O(1)
});
Quick Reference: Time Complexity
// O(1) — Constant time
push(), pop(), at(), with()
// O(n) — Linear time
map(), filter(), reduce(), forEach(), find(), findIndex(),
some(), every(), includes(), indexOf(), flat(1),
concat(), join(), slice(), splice(), shift(), unshift(),
sort() is O(n log n)
// Potentially O(n^2) — Be careful
filter() + indexOf() for deduplication
Nested find()/includes() loops
flatMap() with large sub-arrays
Cheat Sheet: Which Method Should I Use?
When you are staring at a data problem and cannot remember which javascript array method fits, use this quick decision guide:
Need to... Use
----------------------------------------------
Transform every element -> map()
Keep matching elements -> filter()
Accumulate into one value -> reduce()
Find first match -> find()
Find first match index -> findIndex()
Check if any match -> some()
Check if all match -> every()
Check if value exists -> includes()
Run code for each element -> forEach() or for...of
Flatten nested arrays -> flat() or flatMap()
Sort elements -> sort() or toSorted()
Combine arrays -> concat() or spread
Convert to string -> join()
Get a subset -> slice()
Add/remove at any position -> splice() or toSpliced()
Add to end -> push()
Remove from end -> pop()
Add to start -> unshift()
Remove from start -> shift()
Related: Check out our JavaScript Array Methods Cheat Sheet for a quick reference, and our JSON Formatter tool.