A large share of everyday JavaScript is moving data through arrays: picking some items, reshaping them, totting up a number. The built-in array methods express those operations directly, so the code reads as what it does rather than as the mechanics of a loop. Learning the common ones well removes a lot of noise.
The three that do most of the work
map transforms every item into a new one and returns a new array of the same length. filter keeps only the items that pass a test. reduce folds the whole array down to a single value. Together they cover most needs, and they read top to bottom.
const orders = [
{ item: 'pen', price: 2, paid: true },
{ item: 'pad', price: 5, paid: false },
{ item: 'ink', price: 8, paid: true }
];
const paidTotal = orders
.filter((o) => o.paid)
.map((o) => o.price)
.reduce((sum, n) => sum + n, 0); // 10
Each step has one job, and the chain describes the calculation: keep the paid orders, take their prices, add them up. The reduce takes a starting value of 0 as its second argument, which also makes it safe on an empty array.
Finding and testing
When you need one item rather than a new array, find returns the first match and findIndex returns its position. To ask a yes-or-no question about the whole array, some returns true if any item passes, and every returns true only if all do. includes checks for a simple value. These read like plain English and stop as soon as they have an answer.
orders.find((o) => o.item === 'pad'); // the pad order
orders.some((o) => !o.paid); // true: at least one unpaid
orders.every((o) => o.price > 0); // true
Flattening and grouping
flat turns a nested array into a shallower one, and flatMap maps then flattens one level in a single step, which is handy when each item expands into several. For grouping records by a key, the newer Object.groupBy is purpose-built, though a reduce does the same job where it is not yet available.
When a loop is still better
These methods are not always the right choice. A plain for or for...of loop is clearer when you need to stop early on a condition, when each step depends on the previous result in a way reduce would obscure, or in a genuine performance hot path over very large arrays where allocating intermediate arrays matters. The goal is readable intent, not method chains for their own sake. Reach for map, filter and reduce when they make the operation obvious, and keep a loop when it tells the story better.
Building objects with reduce
reduce is not limited to numbers. Its accumulator can be an object, which makes it a clean way to index or group a list. Turning an array of records into a lookup keyed by id, for example, is a single pass.
const byId = users.reduce((acc, u) => {
acc[u.id] = u;
return acc;
}, {});
// byId[42] -> the user with id 42
That said, when the goal is grouping, the newer Object.groupBy states the intent more directly, and a plain loop is just as readable for anyone less comfortable with reduce. The accumulator pattern is worth knowing, but it is a tool to reach for when it genuinely reads better, not a default to force every transformation through. As with the rest of these methods, the test is always whether the next person can read the line and see what it does at a glance.
Common questions
What is the difference between map and forEach?
map transforms each item and returns a new array of results. forEach just runs a function for each item and returns nothing. Use map when you want a new array, forEach only for side effects.
Do array methods like map and filter change the original array?
No. map, filter, reduce, find and similar methods return new values and leave the original untouched. It is sort, reverse and splice that mutate the array in place.
When should I use reduce instead of a loop?
Use reduce when you are combining an array into a single value and the step is simple, such as a sum or building an object. If the logic is complex or needs early exit, a plain loop is usually clearer.
How do I stop a map or filter early?
You cannot, they always process every item. When you need to stop early, use a for...of loop with break, or find if you only want the first match.
