Learning Goals
3 minBy the end of this lesson you will be able to:
- Transform every item in a list with
.map(). - Keep only the items you want with
.filter(). - Pull out a single matching item with
.find(). - Chain two methods together and print the result.
Warm-Up · Six Lines to Add 10%
5 minLast lesson you looped over arrays by hand. Here is a price rise, done the long way.
const prices = [5.5, 2.5, 1.5];
const newPrices = [];
for (let i = 0; i < prices.length; i++) {
newPrices.push(prices[i] * 1.1);
}
console.log(newPrices);Predict together
- How many lines are about the idea (“add 10%”)?
- How many are just bookkeeping — the empty array, the counter, the push?
Reveal
Only one line carries the idea: prices[i] * 1.1. The other five are scaffolding. Today you will write this in a single line that says what you mean, with no counter to get wrong.
New Concept · Machines for Lists
12 minImagine three machines in a kitchen. One changes every item that passes through. One sieves, letting some through and blocking the rest. One searches, stopping at the first match. That is .map(), .filter() and .find().
All three take a function — the arrow functions from Lesson 8. You hand over a small job, and the method runs it on every item for you.
.map() — change every item
const prices = [5.5, 2.5, 1.5];
const withTax = prices.map((price) => price * 1.1);
console.log(prices);
console.log(withTax);[ 5.5, 2.5, 1.5 ]
[ 6.050000000000001, 2.75, 1.6500000000000001 ]Six lines became one. Note the original array is unchanged — .map() always builds a new list of the same length. (Those long decimals are the floating-point wobble from Lesson 4 — round them when you display.)
.filter() — keep some items
The function you pass must answer a yes-or-no question — a boolean, exactly like Lesson 5. Items answering true are kept.
const cheap = prices.filter((price) => price < 3);
console.log(cheap);[ 2.5, 1.5 ].find() — get one item
Same kind of question, but it stops at the first match and hands back that item itself — not a list.
const dishes = ['nasi lemak', 'roti canai', 'nasi goreng'];
const firstNasi = dishes.find((dish) => dish.includes('nasi'));
const missing = dishes.find((dish) => dish.includes('pizza'));
console.log(firstNasi);
console.log(missing);nasi lemak
undefinedNo match gives undefined. Always plan for that — it is the usual cause of a page showing nothing where a name should be.
Which one do I want?
.map()
Returns an array the same length.
Your function returns a new value.
“Give me all the prices, with tax.”
.filter()
Returns an array that is shorter or equal.
Your function returns true or false.
“Give me only the cheap ones.”
.find() is .filter()'s impatient cousin: same question, but it returns one item and stops looking.
Chaining
Each method hands back an array, so you can immediately call another on it. Read left to right, like a sentence.
const labels = prices
.filter((price) => price < 3)
.map((price) => `RM ${price.toFixed(2)}`);
console.log(labels);[ 'RM 2.50', 'RM 1.50' ]“Take the prices, keep the ones under 3, then turn each into a label.” Filter before you map — there is no point transforming items you are about to throw away.
Why it matters
In React you do not write loops to build a page. You write items.map(...) and React renders the result. Lesson 31 (“Lists & Keys”) is this exact method, producing screen elements instead of strings.
Worked Example · Filtering the Menu
12 minBuild this in menu.js.
Step 1 — The data
// menu.js — Warung Aisyah
const dishes = ['nasi lemak', 'roti canai', 'char kway teow', 'cendol'];
const prices = [5.5, 1.5, 8.0, 4.0];Step 2 — Format every price
const labels = prices.map((price) => `RM ${price.toFixed(2)}`);
console.log(labels);[ 'RM 5.50', 'RM 1.50', 'RM 8.00', 'RM 4.00' ]Step 3 — Use the index too
The function can take a second parameter: the item's index. That lets you pair the two arrays without a counting loop.
const lines = dishes.map((dish, i) => `${dish} — RM ${prices[i].toFixed(2)}`);
for (const line of lines) {
console.log(line);
}nasi lemak — RM 5.50
roti canai — RM 1.50
char kway teow — RM 8.00
cendol — RM 4.00Step 4 — Only what the student can afford
Aiman has RM 5 in his pocket:
const POCKET_MONEY = 5;
const affordable = dishes.filter((dish, i) => prices[i] <= POCKET_MONEY);
console.log(`Aiman can afford: ${affordable.join(', ')}`);Aiman can afford: roti canai, cendol.join(', ') glues an array into one string with your chosen separator — handy for printing.
Step 5 — Find one dish
const search = 'cendol';
const found = dishes.find((dish) => dish === search);
if (found) {
console.log(`Yes, we serve ${found}.`);
} else {
console.log(`Sorry, no ${search} today.`);
}Yes, we serve cendol.What changed? The if from Lesson 6 now guards against undefined. Change search to 'pizza' and the else branch handles it cleanly instead of printing undefined at a customer.
Try It Yourself
13 minWork in menu.js or a new methods.js.
Task 1 — Shout the menu
Use
.map()to make a new array of your dish names in capitals, then print it. The original array must be unchanged — print it afterwards to prove it.Task 2 — The expensive half
Use
.filter()to keep only dishes costing more than RM 4, then.map()the result into lines likechar kway teow (RM 8.00).Chain them in one statement, filter first.
Task 3 — A search box
Make a
searchTermvariable. Use.filter()with.includes()to find every dish containing it, and print how many matched.Make it case-insensitive by lowering both sides, as you did in Lesson 5. Test with
'NASI'.
🔥 Mini-Challenge · The Empty Basket
8 minAnjali's shop filter returns an array full of undefined. Find two mistakes.
// anjali-shop.js — buggy
const items = ['kuih', 'satay', 'cendol'];
const prices = [1.5, 12.0, 4.0];
const cheap = items.map((item, i) => {
if (prices[i] < 5) {
return item;
}
});
console.log('Cheap items: ' + cheap);
const satay = items.find((item) => item = 'satay');
console.log('Found: ' + satay);It works if: the cheap list holds exactly kuih and cendol, and the search prints satay.
Reveal the answer
Mistake 1 — map used where filter was meant.
.map() always returns an array of the same length. When the if does not match, the function returns nothing — which is undefined. So the result is:
Cheap items: kuih,,cendolThat gap in the middle is the undefined for satay. Removing items is .filter()'s job, not .map()'s.
Mistake 2 — assignment inside find.
item = 'satay' uses one equals sign — the Lesson 5 trap again. It assigns and hands back 'satay', which is truthy, so .find() matches the very first item and returns kuih.
// anjali-shop.js — fixed
const items = ['kuih', 'satay', 'cendol'];
const prices = [1.5, 12.0, 4.0];
const cheap = items.filter((item, i) => prices[i] < 5);
console.log(`Cheap items: ${cheap.join(', ')}`);
const satay = items.find((item) => item === 'satay');
console.log(`Found: ${satay}`);Cheap items: kuih, cendol
Found: satayA quick test: if your .map() contains an if with no else, you almost certainly wanted .filter().
Recap
3 min.map()transforms every item — the result is the same length..filter()keeps items whose function returnstrue— shorter or equal..find()returns the first matching item, orundefined.- All three take a function, and none of them change the original array.
- The function can take the index as a second parameter.
- Chain them left to right — and filter before you map.
- An
ifwith noelseinside a.map()means you wanted.filter().
New words
- Callback — a function you hand to another function to run for you.
- Transform — turn each item into something new.
- Chaining — calling a method on the result of the previous one.
📦 Homework
4 min to brief · ~20 min to doRequired
- Write
shop.jswith an array of at least six products and a matching array of prices. Using the three methods, print: every product as a formatted label, only those under RM 10, and the result of searching for one product by name. - Handle the “not found” case with an
if. Bring the file next lesson.
Optional stretch
- Look up
.reduce()and use it to total your prices in one line, replacing thesum()function from Lesson 9. - Try
.some()and.every()in the console. Write one sentence each on what they answer.