JavaScript array methods: map, filter, reduce and more
Learn the JavaScript array methods you will use daily: map, filter, find, some, every, reduce and sort, with runnable examples on one shopping cart.

JavaScript array methods let you describe what you want from a list instead of writing the loop that gets it. map transforms every item, filter keeps the ones that match, reduce collapses the array into a single value, and a few more (find, some, every, sort) answer the questions you ask most often. Once you can pick the right one, a lot of loop code turns into a single readable line.
This guide walks through each method on one shopping cart, so you can see how they differ and how they fit together. Every example runs as written.
const cart = [
{ name: "Notebook", price: 12, qty: 2 },
{ name: "Pen", price: 3, qty: 10 },
{ name: "Backpack", price: 45, qty: 1 },
{ name: "Stapler", price: 9, qty: 0 },
]Start from the loop you already know
Say you want the name of every item. With a for...of loop, you build the result by hand:
const names = []
for (const item of cart) {
names.push(item.name)
}
console.log(names) // [ 'Notebook', 'Pen', 'Backpack', 'Stapler' ]That works, and the For Of (opens in a new tab) lesson in JavaScript Basics covers it properly. But three of those lines are bookkeeping: make an empty array, push into it, keep track of it. Array methods remove the bookkeeping. They take a small function, called a callback, that describes what to do with one item, and they run it for every item.
forEach is the simplest of them. It calls your function once per item and returns nothing, so it is the right choice when you only want a side effect like logging. The Foreach (opens in a new tab) lesson in Intermediate JavaScript shows why it is the shape behind the rest.
map: transform every item
map returns a new array with one result for each item in the original. The output always has the same length as the input.
const names = cart.map((item) => item.name)
console.log(names) // [ 'Notebook', 'Pen', 'Backpack', 'Stapler' ]
const lineTotals = cart.map((item) => item.price * item.qty)
console.log(lineTotals) // [ 24, 30, 45, 0 ]The original cart is untouched. Reach for map whenever you think "I want the same list, but each item turned into something else." The Map (opens in a new tab) lesson has you practice it.
filter: keep what matches
filter returns a new array containing only the items for which your callback returns a truthy value. The output can be shorter than the input, or empty.
const inStock = cart.filter((item) => item.qty > 0)
console.log(inStock.map((item) => item.name))
// [ 'Notebook', 'Pen', 'Backpack' ]Your callback can read variables from the code around it, like a minQty you defined earlier. That works because callbacks are closures, and it is the reason array methods feel so flexible. The Filter (opens in a new tab) lesson builds on it.
find, some, and every: ask a question
Sometimes you do not want a new array. You want one item, or a yes or no.
const pen = cart.find((item) => item.name === "Pen")
console.log(pen) // { name: 'Pen', price: 3, qty: 10 }
console.log(cart.find((item) => item.name === "Mug")) // undefined
console.log(cart.some((item) => item.qty === 0)) // true
console.log(cart.every((item) => item.price > 0)) // truefind returns the first match, or undefined if nothing matches, so check before you use the result. some asks whether at least one item passes, and every asks whether all of them do. All three stop as soon as the answer is known. For looking up a plain value like a number or string, the Searching (opens in a new tab) lesson covers simpler tools, and Find And Some (opens in a new tab) covers these.
reduce: collapse to one value
reduce is the one people find intimidating, mostly because of its extra argument. It walks the array while carrying a running value, called the accumulator, and returns whatever the accumulator holds at the end.
const total = cart.reduce((sum, item) => sum + item.price * item.qty, 0)
console.log(total) // 99Read it step by step. The 0 at the end is the starting value for sum. For each item, the callback returns the new sum, and that becomes the sum for the next item: 0, then 24, then 54, then 99, then 99 again for the Stapler. The result of the last call is the result of reduce.
Always pass that starting value. Without it, reduce uses the first item as the start, and on an empty array it throws a TypeError instead of giving you a sensible result. Totals, counts, and averages are the common jobs, and the Reduce Sum (opens in a new tab) lesson goes through them.
The accumulator does not have to be a number. It can be an object, which is handy for lookups:
const priceByName = cart.reduce((lookup, item) => {
lookup[item.name] = item.price
return lookup
}, {})
console.log(priceByName)
// { Notebook: 12, Pen: 3, Backpack: 45, Stapler: 9 }Chain them together
Each of these methods returns an array, so you can call the next one straight on the result. This is the payoff:
const receiptTotal = cart
.filter((item) => item.qty > 0)
.map((item) => item.price * item.qty)
.reduce((sum, amount) => sum + amount, 0)
console.log(receiptTotal) // 99Read it top to bottom as a sentence: keep the items in stock, turn each into a line total, add them up. Every step is an expression that produces a value, which is exactly why they snap together. Put each method on its own line and the chain reads like a recipe. The Chaining (opens in a new tab) lesson is the place to practice it.
sort: order an array, with two catches
sort takes a comparison function that returns a negative number, zero, or a positive number. For prices, subtract one from the other:
const cheapestFirst = [...cart].sort((a, b) => a.price - b.price)
console.log(cheapestFirst.map((item) => item.name))
// [ 'Pen', 'Stapler', 'Notebook', 'Backpack' ]The first catch is in that [...cart]. Unlike map and filter, sort changes the array it is called on. Copying first keeps cart in its original order. This is the same reference behavior covered in value vs reference in JavaScript. Newer runtimes also have toSorted, which does the copy for you.
The second catch is that sort with no comparison function compares items as strings:
console.log([10, 9, 1].sort()) // [ 1, 10, 9 ]Always pass a comparison function for numbers. The Sort (opens in a new tab) lesson goes deeper.
Which method do you need?
| You want to... | Use | Returns |
|---|---|---|
| Run code for each item, nothing back | forEach | undefined |
| Turn every item into something else | map | New array, same length |
| Keep only some items | filter | New array, same or shorter |
| Get the first match | find | One item or undefined |
| Ask if any or all items pass | some / every | true or false |
| Combine everything into one value | reduce | Whatever the accumulator is |
Three mistakes to watch for
Forgetting return when you use braces. An arrow function with { } needs an explicit return, or every result is undefined:
const broken = cart.map((item) => { item.price * item.qty })
console.log(broken) // [ undefined, undefined, undefined, undefined ]Drop the braces for a one-liner, or add return.
Using map when you only want a side effect. If you are not using the array map returns, you wanted forEach.
Passing an async function to map. You get an array of promises, not values. Wrap it in Promise.all and await the whole thing:
const results = await Promise.all(ids.map(async (id) => fetchUser(id)))The Promise All (opens in a new tab) lesson explains why, and async/await explained covers the background.
Where to go from here
The fastest way to make these stick is to rewrite loops you already have. Next time you reach for for and an empty array, ask whether it is really a map, a filter, or a reduce. If the methods feel shaky, start with arrays and loops in JavaScript Basics (opens in a new tab). If you are ready to chain them on real data, Intermediate JavaScript (opens in a new tab) builds a project around exactly that.








