Array methods

You have a list of prices and you want a second list with tax added to each one. You could write a for loop that walks the array, does the sum, and pushes each result into a new array. That works, but it is a lot of wiring for a small idea: take every item and change it. Array methods are the built-in tools for exactly this kind of work. They let you say what you want done to a list without spelling out the loop that does it, and this chapter covers the ones you will reach for daily. They build directly on arrays and functions, so keep both close.
map: change every item
map is a method: a function that belongs to an array and does a job on it. map builds a new array by running each item through a small function you give it, and collecting the results. You pass it that function, and it hands each item over one at a time.
Say you have some prices and want each one doubled:
const prices = [2, 4, 6];
const doubled = prices.map((price) => price * 2);
console.log(doubled); // [4, 8, 12]The (price) => price * 2 part is an arrow function: a short function that takes one item (price) and returns what it should become (price * 2). map calls it once per item and puts each answer in the new array, in the same order.
map takes a list and gives you a new one the same length, with every item run through your little function. The arrow function says what each item turns into, and map does it to all of them in order. Reach for it any time you catch yourself writing a loop only to build a second list. filter: keep the items that pass
Where map changes every item, filter keeps only some of them. You give it a function that answers yes or no for each item, and filter builds a new array from only the items that got a yes.
const scores = [40, 75, 90, 55, 88];
const passing = scores.filter((score) => score >= 60);
console.log(passing); // [75, 90, 88]The function (score) => score >= 60 returns true or false for each score. filter keeps the ones where it is true and drops the rest. The new array can be shorter than the original, and it never changes the order.
filter keeps the items that pass a test and drops the rest, so the new array is often shorter. Your function answers yes or no for each item, and only the yeses come through. It never reorders anything, so what survives stays in the order it started. reduce: boil it down to one value
map and filter both hand you back an array. reduce is the one that collapses an array down to a single value: a total, a maximum, a joined string. It trips people up more than the others, so it is worth going slow.
reduce walks the array while carrying a running result along with it. On each item it asks: given the result so far, and this item, what is the new result?
const prices = [10, 20, 30];
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(total); // 60The function gets two things: sum, the running total so far, and price, the current item. It returns sum + price, which becomes the new running total for the next item. The 0 at the end is where the total starts. So it goes 0 + 10, then 10 + 20, then 30 + 30, landing on 60.
reduce carries a running result through the list and updates it at each item. The callback gets the result so far plus the current item, and returns the new result. The last argument is where you start, usually 0 for a total, and this one clicked for me the moment I read it out loud step by step. find, some, and every
These three are close relatives of filter: they run a test over the array, but instead of a new array they answer a narrower question.
find gives you the first item that passes the test, not a list of all of them. some and every answer true-or-false questions about the whole array.
const scores = [40, 75, 90, 55];
const firstPass = scores.find((score) => score >= 60);
console.log(firstPass); // 75
const anyPass = scores.some((score) => score >= 60);
console.log(anyPass); // true
const allPass = scores.every((score) => score >= 60);
console.log(allPass); // falsefind returns the first matching item (75). some asks "did any item pass?" and returns true because at least one did. every asks "did they all pass?" and returns false because 40 and 55 did not.
find gives you the first item that passes, not a whole list. some asks "did any pass?" and every asks "did they all pass?", and both answer with true or false. Use these when you want one item or a yes-or-no answer, not a filtered array. Chaining and staying readable
The methods above share a design that pays off once you combine them: each one returns a new value and leaves the original array untouched.
map, filter, and the rest never change the array you started with. They give you a new array (or a value) and leave the original alone.
const prices = [10, 20, 30];
const doubled = prices.map((price) => price * 2);
console.log(doubled); // [20, 40, 60]
console.log(prices); // [10, 20, 30]Because map and filter both hand back an array, you can line them up: filter first, then map the survivors.
const prices = [10, 20, 30, 40];
const bigDoubled = prices.filter((price) => price >= 20).map((price) => price * 2);
console.log(bigDoubled); // [40, 60, 80]filter and map both return arrays, you can chain them: filter first, then map what is left. Read the chain from top to bottom, one step at a time. Where to go from here
map, filter, and reduce cover most of what you will do with a list: transform it, narrow it, or collapse it. find, some, and every answer the narrower questions. Once these feel natural, most of your for loops over an array turn into a line or two that says what you meant.
The natural next step is objects, where arrays start holding richer items than plain numbers and strings, and these same methods keep working on them. If any of the callback syntax here felt shaky, a pass back through functions makes the rest click into place.

