JavaScript Array Methods That Actually Matter
A practical guide to map, filter, reduce, find, some, every, flat, and flatMap -- with real-world examples instead of textbook ones.
JavaScript has about 30 array methods. You'll use maybe 8 of them regularly. Here's what they do, when to reach for each one, and -- more importantly -- when not to.
map: Transform Every Item
map returns a new array with each element transformed by your function. The original array stays untouched.
const prices = [10, 25, 50, 100];
const withTax = prices.map(price => price * 1.08);
// [10.8, 27, 54, 108]
Real-world use: you have an array of user objects from your API and need to extract just the emails, or format display names, or build JSX elements from data.
const users = [{ name: 'Ada', role: 'admin' }, { name: 'Bob', role: 'user' }];
const badges = users.map(u => ${u.name} (${u.role}));
// ['Ada (admin)', 'Bob (user)']
Common mistake: using map when you don't need the returned array. If you're just doing something for each item (logging, sending requests), use forEach instead. Using map and ignoring the result is a code smell.
filter: Keep What Matches
Returns a new array with only the elements that pass your test.
const transactions = [
{ amount: 50, type: 'credit' },
{ amount: -20, type: 'debit' },
{ amount: 200, type: 'credit' },
{ amount: -150, type: 'debit' },
];
const deposits = transactions.filter(t => t.type === 'credit');
// [{ amount: 50, type: 'credit' }, { amount: 200, type: 'credit' }]
filter + map is a combo you'll write constantly. Filter down to what you want, then transform it.
const activeUserEmails = users
.filter(u => u.isActive)
.map(u => u.email);
reduce: The Swiss Army Knife
reduce collapses an array into a single value. It's the most powerful array method and also the most abused.
const cart = [
{ item: 'Keyboard', price: 75 },
{ item: 'Mouse', price: 40 },
{ item: 'Monitor', price: 350 },
];
const total = cart.reduce((sum, product) => sum + product.price, 0);
// 465
You can technically use reduce to do anything -- build objects, flatten arrays, implement map and filter. But just because you can doesn't mean you should. If your reduce callback is more than 2-3 lines, there's probably a clearer way to write it.
Good use of reduce -- grouping items:
const orders = [
{ status: 'shipped', id: 1 },
{ status: 'pending', id: 2 },
{ status: 'shipped', id: 3 },
];
const grouped = orders.reduce((acc, order) => {
acc[order.status] = acc[order.status] || [];
acc[order.status].push(order);
return acc;
}, {});
// { shipped: [{...}, {...}], pending: [{...}] }
With Object.groupBy now available in modern environments, even this use case is becoming less common.
find and findIndex: Grab the First Match
find returns the first element that matches. Not an array -- the element itself (or undefined).
const users = [
{ id: 1, name: 'Ada' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
const bob = users.find(u => u.id === 2);
// { id: 2, name: 'Bob' }
findIndex does the same but returns the index. Useful when you need to splice or replace an item in place.
some and every: Boolean Checks
some returns true if at least one element passes the test. every returns true only if all elements pass.
const passwords = ['abc', 'hunter2', 'correct-horse-battery-staple'];
const hasWeakPassword = passwords.some(p => p.length < 8); // true
const allStrong = passwords.every(p => p.length >= 8); // false
These short-circuit -- some stops at the first true, every stops at the first false. Use them instead of writing .filter(...).length > 0.
flat and flatMap: Dealing with Nested Arrays
flat un-nests arrays by one level (or more, if you pass a depth).
const nested = [[1, 2], [3, 4], [5, [6, 7]]];
nested.flat(); // [1, 2, 3, 4, 5, [6, 7]]
nested.flat(2); // [1, 2, 3, 4, 5, 6, 7]
flatMap is map + flat(1) in one step. It's perfect when your map function returns arrays and you want them merged.
const sentences = ['hello world', 'foo bar baz'];
const words = sentences.flatMap(s => s.split(' '));
// ['hello', 'world', 'foo', 'bar', 'baz']
Without flatMap, you'd get [['hello', 'world'], ['foo', 'bar', 'baz']] and need a separate .flat().
forEach: When You Don't Need a Return Value
forEach is for side effects -- logging, DOM manipulation, sending analytics events. It returns undefined.
errors.forEach(err => console.error(err.message));
You can't break out of a forEach. If you need early termination, use a for...of loop instead.
Chaining: Where It Gets Fun
The real power shows up when you chain these together:
const topSpenders = orders
.filter(o => o.status === 'completed')
.map(o => ({ name: o.customerName, total: o.items.reduce((s, i) => s + i.price, 0) }))
.filter(c => c.total > 100)
.sort((a, b) => b.total - a.total)
.slice(0, 5);
Readable, declarative, and each step is independently testable. If you want to practice chaining these methods on real problems, CodeUp has interactive JavaScript exercises that build from single methods to complex chains.
One performance note: each method in the chain creates a new array. For most cases this is irrelevant. If you're processing tens of thousands of items and performance matters, a single for loop that does everything in one pass will be faster. But write the readable version first and optimize only when you have evidence it's slow.