"JavaScript Array Methods: map, filter, reduce, and forEach"
The core higher-order array methods, what each one returns, and when to reach for it.
2 min read
map, filter, reduce, and forEach are higher-order functions — they take a function as an argument and apply it to each element of an array. Together they replace most manual for loops over arrays with something shorter and more declarative about what the code is doing, not just how.
forEach — run something for each item
const nums = [1, 2, 3];
nums.forEach(n => console.log(n * 2));
// Logs: 2, 4, 6forEach always returns undefined. It's for side effects (logging, pushing into an outside array, updating the DOM) — not for producing a new array. If you find yourself trying to build a result from inside a forEach, that's usually a sign you want map or reduce instead.
map — transform each item
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);
console.log(doubled); // [2, 4, 6]map returns a new array of the same length, with each item transformed by the callback. The original array is untouched.
filter — keep only some items
const nums = [1, 2, 3, 4, 5, 6];
const evens = nums.filter(n => n % 2 === 0);
console.log(evens); // [2, 4, 6]filter returns a new array containing only the elements for which the callback returned a truthy value — the array can be shorter than the original, or empty.
reduce — combine everything into one value
const nums = [1, 2, 3, 4];
const total = nums.reduce((accumulator, current) => accumulator + current, 0);
console.log(total); // 10reduce takes a callback and a starting value (0 here), then runs the callback once per element, carrying an accumulator forward each time. It's the most general of the four — map and filter can technically both be written with reduce — but reach for map/filter when they fit, since they state their intent more clearly. reduce earns its place for things they can't express directly, like collapsing an array into a single total, object, or grouped structure:
const words = ["a", "bb", "ccc", "dd"];
const byLength = words.reduce((groups, word) => {
const key = word.length;
groups[key] = groups[key] || [];
groups[key].push(word);
return groups;
}, {});
// { 1: ["a"], 2: ["bb", "dd"], 3: ["ccc"] }Chaining them together
Since map and filter return new arrays, they chain naturally:
const orders = [
{ item: "book", price: 12, paid: true },
{ item: "pen", price: 2, paid: false },
{ item: "laptop", price: 999, paid: true },
];
const paidTotal = orders
.filter(order => order.paid)
.map(order => order.price)
.reduce((sum, price) => sum + price, 0);
console.log(paidTotal); // 1011Each step does one clear thing, and reading top to bottom tells you exactly what transformation the data goes through — filter down to paid orders, pull out their prices, sum them.
With arrays, objects, and the methods that transform them covered, the next section moves from data to the page itself: the DOM.