Array Methods
Arrays are one of the most common data structures in JavaScript, and the language ships with a powerful set of built-in methods for working with them. Instead of writing manual loops for every operation, array methods let you express intent clearly and concisely. In this lesson you will learn the most important ones and understand when to reach for each.
Transforming Data with map
Array.prototype.map creates a new array by applying a function to every element. The original array is never modified.
const products = [
{ name: "Keyboard", price: 79 },
{ name: "Mouse", price: 45 },
{ name: "Monitor", price: 320 },
];
// Add a discounted price to every product
const discounted = products.map((product) => ({
...product,
salePrice: (product.price * 0.9).toFixed(2),
}));
console.log(discounted);
// Each object now has both price and salePrice
Notice that map always returns an array of the same length as the input. If you have 3 products going in, you get 3 products coming out — just transformed.
Filtering Data with filter
Array.prototype.filter creates a new array containing only the elements for which the callback returns a truthy value.
const scores = [42, 88, 61, 95, 73, 30, 100, 54];
const passing = scores.filter((score) => score >= 60);
const failing = scores.filter((score) => score < 60);
console.log("Passing scores:", passing);
console.log("Failing scores:", failing);
console.log("Pass rate:", `${Math.round((passing.length / scores.length) * 100)}%`);
You can chain map and filter together. For example, to get the names of expensive products:
const inventory = [
{ name: "USB Hub", price: 25, inStock: true },
{ name: "Webcam", price: 89, inStock: false },
{ name: "Headset", price: 149, inStock: true },
{ name: "Desk Lamp", price: 39, inStock: true },
{ name: "Chair Mat", price: 55, inStock: false },
];
const availableExpensive = inventory
.filter((item) => item.inStock && item.price > 40)
.map((item) => item.name);
console.log("Available items over $40:", availableExpensive);
// [ 'Headset' ] — Desk Lamp ($39) fails the > 40 test; Webcam and Chair Mat are out of stock
Chaining works because each method returns a new array, so you can call the next method directly on the result.
Predict
Trace this pipeline by hand before running it. What does it log?
const products = [
{ name: "Pen", price: 3, inStock: true },
{ name: "Notebook", price: 12, inStock: false },
{ name: "Backpack", price: 60, inStock: true },
{ name: "Water Bottle", price: 18, inStock: true },
];
const result = products
.filter((p) => p.inStock)
.map((p) => p.price)
.filter((price) => price > 10);
console.log(result);Reducing Arrays with reduce
Array.prototype.reduce is the most flexible array method. It collapses an array into a single value by accumulating results across each element.
The signature is: array.reduce(callback, initialValue). The callback receives the accumulator (running result) and the current element.
const orders = [
{ id: 1, total: 45.99 },
{ id: 2, total: 120.00 },
{ id: 3, total: 8.50 },
{ id: 4, total: 67.25 },
];
// Sum all order totals
const grandTotal = orders.reduce((sum, order) => sum + order.total, 0);
console.log("Grand total: $" + grandTotal.toFixed(2));
// Group orders by whether they are over $50
const grouped = orders.reduce(
(groups, order) => {
const key = order.total >= 50 ? "large" : "small";
groups[key].push(order);
return groups;
},
{ large: [], small: [] }
);
console.log("Large orders:", grouped.large.length);
console.log("Small orders:", grouped.small.length);
Always provide an explicit initialValue (the second argument to reduce). Without it, reduce uses the first array element as the accumulator, which causes confusing bugs when working with arrays of objects.
Debug
This code is supposed to sum the prices and log 'Total: $444'. It doesn't throw — it prints something worse. Predict what it actually prints, then fix it so it logs 'Total: $444'.
const assert = require('assert');
const products = [
{ name: "Keyboard", price: 79 },
{ name: "Mouse", price: 45 },
{ name: "Monitor", price: 320 },
];
const total = products.reduce((sum, product) => sum + product.price);
assert.strictEqual(total, 444, 'expected 444, got ' + total);
console.log("Total: $" + total);Expected output: Total: $444
Finding Elements
When you need a single element rather than a filtered list, use find and findIndex.
findreturns the first matching element (orundefinedif none match)findIndexreturns the index of the first matching element (or-1if none match)
const users = [
{ id: 1, name: "Alice", role: "admin" },
{ id: 2, name: "Bob", role: "editor" },
{ id: 3, name: "Carol", role: "viewer" },
{ id: 4, name: "Dan", role: "editor" },
];
const admin = users.find((user) => user.role === "admin");
console.log("Admin:", admin.name);
const bobIndex = users.findIndex((user) => user.name === "Bob");
console.log("Bob is at index:", bobIndex);
// Safe lookup — find returns undefined if not found
const missing = users.find((user) => user.id === 99);
console.log("Missing user:", missing); // undefined
Testing Array Contents with some and every
Sometimes you do not need the elements themselves — you just need a yes/no answer about the collection.
somereturnstrueif at least one element satisfies the conditioneveryreturnstrueif all elements satisfy the condition
const cart = [
{ name: "Notebook", price: 12, available: true },
{ name: "Pen Set", price: 8, available: true },
{ name: "Stapler", price: 15, available: false },
];
const anyUnavailable = cart.some((item) => !item.available);
const allAffordable = cart.every((item) => item.price < 20);
const allAvailable = cart.every((item) => item.available);
console.log("Any unavailable?", anyUnavailable); // true
console.log("All affordable?", allAffordable); // true
console.log("All available?", allAvailable); // false
if (anyUnavailable) {
const unavailable = cart.filter((item) => !item.available).map((i) => i.name);
console.log("Out of stock:", unavailable.join(", "));
}
Recall
Without scrolling up: you call three methods on the same array of objects — map, filter, and reduce (with an initial value of 0). map and filter each return one thing, reduce returns another. Which row correctly describes what each RETURNS?
Try It Yourself
Reading about array methods is not the same as reaching for them by intent. This is a build task: a small program that reports its own pass/fail. You are given a task list — an array of task objects — and three empty functions to finish. Run it and it fails immediately, telling you which function is still missing. Implement each one until every check passes and it prints All checks passed.
The three functions reuse exactly the methods this lesson taught: chaining filter into map to select and reshape, reduce with an explicit initial value to aggregate, and some to answer a yes/no question about the collection. The starter already has the data, the stubs, and the checks — you write only the logic inside each function. Nothing above spells out all three answers, so you will have to assemble them yourself.
Build
Finish the build. Three functions are stubbed out and the checks below them fail until each one returns the right value. Run it as-is to see which check fails first, decide what that function is missing, then implement the three functions until it prints 'All checks passed.' The checks run top to bottom, so the first failure you see is TODO 1 — implement it first, then work down.
const assert = require('assert');
// The data: a task list for the manager service. Do NOT change this array.
const tasks = [
{ title: "Write spec", status: "done", priority: 3 },
{ title: "Review PR", status: "pending", priority: 5 },
{ title: "Fix bug", status: "pending", priority: 8 },
{ title: "Deploy", status: "done", priority: 2 },
{ title: "Update docs", status: "pending", priority: 4 },
];
// TODO 1: return a NEW array of the titles of only the pending tasks, in order.
// pendingTitles(tasks) -> ["Review PR", "Fix bug", "Update docs"]
function pendingTitles(tasks) {
// your code here
}
// TODO 2: return the sum of every task's priority as a number.
// totalPriority(tasks) -> 22
function totalPriority(tasks) {
// your code here
}
// TODO 3: return true if ANY task has a priority of 8 or higher, else false.
// hasUrgent(tasks) -> true
function hasUrgent(tasks) {
// your code here
}
// --- Build checks: these must all pass. Do not edit below this line. ---
assert.deepStrictEqual(
pendingTitles(tasks),
["Review PR", "Fix bug", "Update docs"],
"pendingTitles(tasks) should filter to pending tasks and map them to their titles, in order",
);
assert.strictEqual(
totalPriority(tasks),
22,
"totalPriority(tasks) should reduce every task's priority into a single sum (22)",
);
assert.strictEqual(
hasUrgent(tasks),
true,
"hasUrgent(tasks) should return true when at least one task has priority >= 8",
);
console.log("All checks passed.");
console.log("Pending titles:", pendingTitles(tasks));
console.log("Total priority:", totalPriority(tasks));
console.log("Any urgent?", hasUrgent(tasks));Expected output: All checks passed.
Pending titles: [ 'Review PR', 'Fix bug', 'Update docs' ]
Total priority: 22
Any urgent? true
Once it passes, try two variations and predict each before running:
- Flip the filter predicate. In
pendingTitles, change thefiltertest fromstatus === "pending"tostatus === "done". Predict which titles come back, in order, before running. You now select the two done tasks and map them to["Write spec", "Deploy"], so the check fails — proof that thefilterpredicate, not themap, decides which rows survive. somevsevery. InhasUrgent, swapsomeforevery, keeping the samepriority >= 8test. Decide whathasUrgent(tasks)returns before running.everydemands all tasks clear the bar, and most tasks sit well under8, so it returnsfalseand the check fails — the difference between "at least one" and "all".
Capstone milestone
Milestone — the Task Manager service. The capstone's service (Step 3 of the capstone project) filters, sorts, and aggregates tasks with exactly these array methods. This lesson's exercises are that skill in miniature. Confirm you can reach for each method by intent.
Hint: You don't need the full capstone service yet — this confirms the map/filter/reduce fluency the service is built on. In the capstone, these same methods count pending tasks, filter by status, and build the stats line.
- Used filter to select a subset of items by a condition
- Used map to transform items into a new array without mutating the original
- Used reduce with an explicit initial value to compute an aggregate (a sum, count, or grouping)
- Used find (or some/every) to answer a single-item or yes/no question about the collection
Key Takeaways
maptransforms every element and returns a new array of the same length — use it when you need to reshape datafilterreturns a new array containing only elements that pass a test — the original array is never mutatedreduceis the Swiss Army knife: it can replicatemapandfilter, compute aggregates, and build complex data structuresfindandfindIndexstop at the first match, so they save exactly the part of the array they skip — a big win when the match is near the front, and no real win when it is near the end or missing, since then both they andfilterscan everythingsomeandeveryreturn booleans and short-circuit early, so they are ideal for validation checks- All of these methods accept a callback function, making them composable and chainable
- None of these methods mutate the original array (unlike
push,pop,splice, orsort)
Pro Tip: Reach for
map,filter, andreducebefore writing aforloop. They signal intent clearly — a reader seeingfilterimmediately knows you are selecting a subset, whereas aforloop requires reading the body to understand what it does. When you do need a loop (for side effects like logging or DOM updates),forEachis the idiomatic choice.
Next Steps
Now that you can transform arrays with confidence, the next lesson covers destructuring and the spread operator — two features that make working with arrays and objects dramatically more concise.
Next lesson
Destructuring and Spread
Learn JavaScript destructuring and the spread operator. Unpack arrays and objects to write cleaner, more expressive modern JavaScript.
20 min