map, filter and reduce
Most array tasks come down to three actions: change every element, pick the matching ones, or calculate a total. The methods map(), filter() and reduce() exist for exactly that. Code using them is shorter than a loop, and the method name tells you right away what it does.
map — transform every element
map() calls a function for each element and collects the results in a new array of the same length:
const numbers = [1, 2, 3];
const doubled = numbers.map((n) => n * 2);
console.log(doubled.join(', ')); // 2, 4, 6The original numbers array does not change — map() always returns a new one.
filter — pick the matching ones
filter() keeps only the elements for which the function returned true. Such a checking function is called a condition, or a predicate:
const numbers = [5, 12, 8, 20];
const big = numbers.filter((n) => n > 10);
console.log(big.join(', ')); // 12, 20If no element matches, the result is an empty array.
reduce — boil down to one value
reduce() walks through the array and accumulates a result. The function receives the accumulated value (often named sum or acc) and the current element, and the second argument of reduce() is the starting value:
const prices = [100, 250, 400];
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(total); // 750On the first step sum is 0, on the second 100, on the third 350, and the final result is 750.
An array of objects
Most often these methods work with arrays of objects. An object is a value in curly braces that stores data under names: product.title reads the title property. Objects are covered in detail in the next chapter.
const products = [
{ title: 'Tea', price: 5 },
{ title: 'Coffee', price: 12 },
];
const titles = products.map((product) => product.title);
console.log(titles.join(', ')); // Tea, CoffeeChaining methods
map() and filter() return an array, so the next method can be called right after the previous one:
const orders = [
{ total: 500, paid: true },
{ total: 300, paid: false },
{ total: 200, paid: true },
];
const paidSum = orders
.filter((order) => order.paid)
.map((order) => order.total)
.reduce((sum, total) => sum + total, 0);
console.log(paidSum); // 700Read the chain from top to bottom: paid orders, their totals, the grand total.
Common mistake
If the body of an arrow function is wrapped in curly braces, the value must be returned with return. Without it the function returns undefined:
const numbers = [1, 2, 3];
const wrong = numbers.map((n) => { n * 2; });
const right = numbers.map((n) => { return n * 2; });
console.log(wrong[0]); // undefined
console.log(right.join(', ')); // 2, 4, 6In the short form without braces, (n) => n * 2, the return is implied.