JS Sketchbooksee JavaScript think ✏️
← back to phase 4

4.9 — map / filter / reduce

Every list job you'll ever do is one of three shapes: transform every element (prices → prices with tax), keep some elements (only the failures), or boil everything down to one value (the total). You could write a for loop for each. Professionals mostly don't.

Arrays ship the three shapes as methods — map, filter, reduce — and each takes a function as its argument (lesson 3.8's callbacks, now earning their keep daily). You describe what happens to one element; the method runs the loop.

This trio is the single most-used pattern in modern JavaScript — and the exact shape of every test-report you'll ever crunch.

watch it happen
const prices = [120, 45, 200, 80];

const withTax = prices.map(p => p * 1.1);

const cheap = prices.filter(p => p < 100);

const total = prices.reduce(
  (sum, p) => sum + p,
  0
);

console.log(withTax.length);
console.log(cheap);
console.log(total);

One input array, three machines. Each machine takes YOUR function — written right there as an arrow function — and applies it element by element. You never write the loop; you write what one element deserves.

prices — the input belt1204520080three machines, one belt — you write the per-element function,they run the loop
under the hood

The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”

All three call your function once per element and never touch the original array. That makes chains natural: runs.filter(...).map(...) — each link takes the previous link's new array. Read chains top-down as a pipeline: “keep the failures, then take their names.”

reduce((acc, el) => …, start) is the general one — map and filter could both be written with it.

The two classic stumbles. Forgetting the starting value — JS then uses the first element, which breaks on empty arrays. And forgetting to return the next accumulator — then the next lap receives undefined (lesson 3.3's chute rule, striking again).

Fun fact: your photo app runs this exact trio every day. “Show 2024 photos” is a filter. The thumbnail grid is a map — every photo → a small version. “Storage used: 48 GB” is a reduce. You've been a pipeline user for years; now you're the one writing the stations.

your turn

⌨️ wishlist, discounted and budgeted

A sale hits your wishlist: every price drops, you keep what fits the budget, and you total the damage — all without writing a single loop yourself.

requirements:

  • Start with wishlist = [1200, 350, 99, 500].
  • Take 50 off every price → a new array named discounted.
  • From discounted, keep only prices ≤ 450 → print that array.
  • Print the SUM of all discounted prices — a single value, built with a starting value of 0.

when you press RUN, the console must show exactly:

[300,49,450]
1949

✏️ Quick check 1

Type the resulting array exactly (no spaces):

console.log([1, 2, 3].map(n => n * 2));

✏️ Quick check 2

Type exactly what this prints:

console.log([5, 12, 8].filter(n => n > 9).length);

✏️ Quick check 3

Careful with the second argument — type what this prints:

console.log([1, 2, 3].reduce((a, n) => a + n, 10));
teach it back

🗣️ Now teach it back

Explain map, filter, and reduce to a friend using one everyday example for all three (a playlist, a shopping cart, photos — your pick). Include what each returns and what happens to the original array.

Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.

a few sentences, minimum — you’ve got this
to remember
map TRANSFORMS every element → new array, same count. filter KEEPS passers → new array, ≤ count, elements unchanged. reduce BOILS DOWN → one value.
All three take your per-element function (callbacks!), run the loop for you, and never mutate the original.
reduce((acc, el) => nextAcc, start): read the starting value first; every lap must RETURN the next accumulator.
next: 4.10 Sorting & finding →