Learning Goals
3 minBy the end of this lesson you will be able to:
- Create an object with key–value pairs and read them with a dot.
- Build an array of objects and loop over it.
- Unpack values with destructuring in one line.
- Use
.map()and.filter()on objects to print a real menu.
Warm-Up · Out of Step
5 minIn Lessons 9 and 10 you kept two arrays side by side. Here Hafiz adds a dish.
const dishes = ['nasi lemak', 'roti canai', 'cendol'];
const prices = [5.5, 1.5, 4.0];
dishes.push('satay');
console.log(dishes[3], prices[3]);Predict together
- What exactly will that last line print?
- Whose fault is it — and would any error message tell you?
Reveal
satay undefinedOnly dishes was pushed to, so the two arrays no longer line up. No error, no warning — just undefined where a price should be. Today you keep the name and the price together, so they cannot drift apart.
New Concept · Facts That Belong Together
12 minAn array is a numbered row of lockers. An object is a form you fill in: each blank has a label rather than a number. Name, price, spicy — all on one form, describing one dish.
Making an object
const dish = {
name: 'nasi lemak',
price: 5.5,
isSpicy: true,
};
console.log(dish.name);
console.log(dish.price);nasi lemak
5.5Curly braces, then key: value pairs separated by commas. Read a value with a dot and the key name.
Array
Ordered. Reached by number: dishes[0].
For many of the same thing.
Object
Labelled. Reached by name: dish.price.
For many facts about one thing.
Changing and adding
dish.price = 6.0; // change a value
dish.portion = 'large'; // add a brand-new key
console.log(dish);{ name: 'nasi lemak', price: 6, isSpicy: true, portion: 'large' }As with arrays in Lesson 9, const does not freeze the contents — it only stops you pointing the name at a different object.
Reading a key that is not there gives undefined, quietly:
console.log(dish.calories);undefinedAn array of objects
This is the shape of real data. Every API you meet in Section C hands you exactly this.
const menu = [
{ name: 'nasi lemak', price: 5.5, isSpicy: true },
{ name: 'roti canai', price: 1.5, isSpicy: false },
{ name: 'cendol', price: 4.0, isSpicy: false },
];
for (const item of menu) {
console.log(`${item.name} — RM ${item.price.toFixed(2)}`);
}nasi lemak — RM 5.50
roti canai — RM 1.50
cendol — RM 4.00Now adding a dish means adding one object with both facts inside. The Warm-Up bug becomes impossible.
Destructuring — unpacking in one line
Writing item.name and item.price over and over gets noisy. Destructuring pulls keys out into variables:
const { name, price } = menu[0];
console.log(name, price);nasi lemak 5.5The braces on the left mean “take these keys out”. The variable names must match the key names. It works beautifully in a function's parameters:
function describe({ name, price }) {
return `${name} costs RM ${price.toFixed(2)}`;
}
console.log(describe(menu[1]));roti canai costs RM 1.50Look closely at that function signature. That is exactly how React components receive their props — you will write it hundreds of times from Lesson 27 onwards.
Objects with array methods
const cheap = menu.filter((item) => item.price < 5);
const names = menu.map(({ name }) => name);
console.log(cheap.length, names);2 [ 'nasi lemak', 'roti canai', 'cendol' ]Why it matters
Objects inside arrays, handled with .map() and .filter(), then destructured into a function — that single sentence describes most React code ever written. You now have all four pieces.
Worked Example · A Proper Menu
12 minRebuild the warung menu properly in menu2.js.
Step 1 — One object per dish
// menu2.js — Warung Aisyah, one object per dish
const menu = [
{ name: 'nasi lemak', price: 5.5, isSpicy: true, inStock: true },
{ name: 'roti canai', price: 1.5, isSpicy: false, inStock: true },
{ name: 'char kway teow', price: 8.0, isSpicy: true, inStock: false },
{ name: 'cendol', price: 4.0, isSpicy: false, inStock: true },
];
console.log(`${menu.length} dishes on the menu`);4 dishes on the menuStep 2 — A formatting function
Destructure the parameter so the body reads cleanly:
function menuLine({ name, price, isSpicy }) {
const chilli = isSpicy ? ' 🌶️' : '';
return `${name}${chilli} — RM ${price.toFixed(2)}`;
}
console.log(menuLine(menu[0]));nasi lemak 🌶️ — RM 5.50That ? : is the ternary — a compact if/else that gives back a value. Read it as “if spicy, use the chilli, otherwise use nothing”.
Step 3 — Print only what is available
const available = menu.filter((item) => item.inStock);
for (const item of available) {
console.log(menuLine(item));
}nasi lemak 🌶️ — RM 5.50
roti canai — RM 1.50
cendol — RM 4.00Char kway teow is out of stock, so it never reaches the loop. Note item.inStock is already a boolean — no === true needed.
Step 4 — Total the available dishes
let total = 0;
for (const { price } of available) {
total = total + price;
}
console.log(`Buying one of each: RM ${total.toFixed(2)}`);Buying one of each: RM 11.00You can destructure right inside the for…of header. Only price is unpacked, because that is all this loop needs.
Step 5 — Add a dish, safely
menu.push({ name: 'satay', price: 12.0, isSpicy: false, inStock: true });
console.log(menuLine(menu[menu.length - 1]));satay — RM 12.00What changed? Compare this with the Warm-Up. One .push() carried every fact about satay, so nothing could fall out of step. Forgetting a key would be obvious the moment you printed the line — and you cannot forget the price, because the object would look plainly incomplete.
Try It Yourself
13 minWork in menu2.js or a new objects.js.
Task 1 — Your own catalogue
Build an array of five objects for a shop you invent. Each needs at least four keys, including one boolean and one number. Print the whole array, then just the third item's name.
Task 2 — A card function
Write a function taking a destructured object and returning a two-line description as a template literal. Use it inside a
.map(), then print every card.Task 3 — Search and report
Use
.find()to look up an item by name. If it exists, print its price; if not, print a polite message. Then use.filter()to count how many items are in stock.Finally, add a new key to one object after creating it, and print the object to confirm it is there.
🔥 Mini-Challenge · The Object That Prints Itself Wrong
8 minPei Shan's stock report shows [object Object] and a wrong count. Find two mistakes.
// peishan-stock.js — buggy
const stock = [
{ item: 'kuih', qty: 12 },
{ item: 'satay', qty: 0 },
{ item: 'cendol', qty: 7 },
];
for (const row of stock) {
console.log('In stock: ' + row);
}
const inStock = stock.filter((row) => row.qty);
console.log('Lines in stock: ' + inStock.length);
const missing = stock.find((row) => row.item === 'roti');
console.log('Found: ' + missing.item);It works if: each line names its item and quantity, the in-stock count is 2, and the missing search says so politely instead of crashing.
Reveal the answer
Mistake 1 — printing the whole object into a string.
Joining an object to text with + converts it clumsily:
In stock: [object Object]You must name the keys you want. (The count is right, incidentally — qty: 0 is falsy, so satay is correctly excluded. That one works by luck rather than intent, so make it explicit.)
Mistake 2 — using a find result without checking it.
There is no roti, so missing is undefined, and reading .item on it throws:
TypeError: Cannot read properties of undefined (reading 'item')This is the single most common runtime error in JavaScript. Always guard a .find() result.
// peishan-stock.js — fixed
for (const { item, qty } of stock) {
console.log(`In stock: ${item} — ${qty}`);
}
const inStock = stock.filter((row) => row.qty > 0); // explicit
console.log(`Lines in stock: ${inStock.length}`);
const missing = stock.find((row) => row.item === 'roti');
if (missing) {
console.log(`Found: ${missing.item}`);
} else {
console.log('Sorry, we do not stock roti.');
}In stock: kuih — 12
In stock: satay — 0
In stock: cendol — 7
Lines in stock: 2
Sorry, we do not stock roti.Recap
3 min- An object holds
key: valuepairs in curly braces. - Read a value with a dot:
dish.price. A missing key givesundefined. - Arrays are for many things; objects are for many facts about one thing.
- An array of objects is the shape almost all real data takes.
- Destructuring —
const { name, price } = dish;— unpacks keys into variables. - Destructured parameters are exactly how React components receive props.
- Always guard a
.find()result before reading a key from it.
New words
- Object — a labelled collection of key–value pairs.
- Key / property — the label; value — what it holds.
- Destructuring — unpacking keys into variables in one line.
- Ternary —
condition ? a : b, a compact if/else that returns a value.
📦 Homework
4 min to brief · ~20 min to doRequired
- Rewrite your Lesson 10
shop.jsto use an array of objects instead of two parallel arrays. Keep all the same output. - Add one function that takes a destructured object and returns a formatted line, and use it inside a
.map(). Bring the file next lesson.
Optional stretch
- Nest an object inside an object — give each dish a
stall: { name, town }key — and printdish.stall.town. - Look up
Object.keys()and use it to print every key name of one dish without typing them out.