Learning Goals
3 minBy the end of this lesson you will be able to:
- Repeat code a fixed number of times with a
forloop. - Read the three parts of a
forloop header out loud. - Build a running total inside a loop.
- Spot an infinite loop before you run it.
Warm-Up · Copy and Paste Gone Wrong
5 minLast lesson your code made decisions. Here Adrian prints a five-table seating plan by hand.
console.log('Table 1');
console.log('Table 2');
console.log('Table 3');
console.log('Table 3');
console.log('Table 5');Predict together
- Spot the mistake. How long did it take you?
- Now imagine the restaurant has 120 tables. What could go wrong?
Reveal
Table 3 appears twice and table 4 is missing — a classic copy-paste slip that is easy to miss and hard to spot. With 120 tables you would almost certainly make several. A loop writes the line once, so this bug becomes impossible.
New Concept · Say It Once, Run It Often
12 minThink of a running track. You start at lap 1, check whether you have finished, run the lap, then add one to your count. Round and round until the check fails. A for loop has those same four moments.
The for loop
for (let i = 1; i <= 5; i++) {
console.log(`Table ${i}`);
}Table 1
Table 2
Table 3
Table 4
Table 5The header has three parts, separated by semicolons:
let i = 1i <= 5i++Read it aloud: “start i at 1; keep going while i is 5 or less; add one to i after each pass.”
i++ is shorthand for i = i + 1. The name i is short for index — a long tradition, and fine for a counter. Anything more meaningful deserves a real name.
Counting from zero
Programmers usually start at 0, because lists are numbered from zero (you saw that with string characters in Lesson 3).
for (let i = 0; i < 3; i++) {
console.log(`Index ${i}`);
}Index 0
Index 1
Index 2Note it is <, not <=. Starting at 0 and stopping before 3 gives you exactly three passes.
Building a total
Declare the total outside the loop, then add to it inside. Declaring it inside would reset it every pass.
const PRICE = 2.5;
let total = 0;
for (let cup = 1; cup <= 4; cup++) {
total = total + PRICE;
console.log(`Cup ${cup} — running total RM ${total}`);
}Cup 1 — running total RM 2.5
Cup 2 — running total RM 5
Cup 3 — running total RM 7.5
Cup 4 — running total RM 10When you do not know how many times
A while loop repeats as long as a condition holds. Use it when the number of passes depends on something changing.
let stock = 3;
while (stock > 0) {
console.log(`Selling one — ${stock} left before sale`);
stock = stock - 1;
}
console.log('Sold out!');Selling one — 3 left before sale
Selling one — 2 left before sale
Selling one — 1 left before sale
Sold out!for
You know the count up front.
“Print 20 tables.”
Counter is built into the header — hard to forget.
while
You stop when something becomes true.
“Keep selling until stock runs out.”
You must change the condition, or it never ends.
The infinite loop
Forget the line that moves things forward and the loop never stops. The browser tab freezes.
let stock = 3;
while (stock > 0) {
console.log('Selling one');
// stock never changes — this runs forever
}Before running any while, ask yourself: what inside this loop makes the condition eventually false? If you cannot answer, do not run it.
Why it matters
Loops are how a page shows twenty products from twenty rows of data. In Lesson 10 you will meet .map(), which does this more neatly — but it is a loop underneath, and React uses it on every list you ever render.
Worked Example · The Kuih Order
12 minPriya is buying kuih for a Hari Raya open house. Build this in kuih.js.
Step 1 — Count the pieces
// kuih.js — 8 pieces for the open house
const PIECES = 8;
for (let i = 1; i <= PIECES; i++) {
console.log(`Piece ${i} packed`);
}Piece 1 packed
Piece 2 packed
Piece 3 packed
Piece 4 packed
Piece 5 packed
Piece 6 packed
Piece 7 packed
Piece 8 packedChange PIECES to 40 and run it. One edit, forty lines. That is the whole point.
Step 2 — Add up the cost
const PRICE = 1.5;
let total = 0;
for (let i = 1; i <= PIECES; i++) {
total = total + PRICE;
}
console.log(`${PIECES} pieces cost RM ${total.toFixed(2)}`);8 pieces cost RM 12.00Step 3 — Decide inside the loop
Every third piece is a free sample. An if from last lesson goes straight inside the loop body:
let total = 0;
for (let i = 1; i <= PIECES; i++) {
if (i % 3 === 0) {
console.log(`Piece ${i} — free sample!`);
} else {
total = total + PRICE;
console.log(`Piece ${i} — RM ${PRICE}`);
}
}
console.log(`Total to pay: RM ${total.toFixed(2)}`);Piece 1 — RM 1.5
Piece 2 — RM 1.5
Piece 3 — free sample!
Piece 4 — RM 1.5
Piece 5 — RM 1.5
Piece 6 — free sample!
Piece 7 — RM 1.5
Piece 8 — RM 1.5
Total to pay: RM 9.00The % operator from Lesson 4 does the work: i % 3 === 0 is true on 3, 6, 9 and so on.
Step 4 — Count backwards
A loop can run down as easily as up. Swap the start, the test and the step:
for (let i = 3; i >= 1; i--) {
console.log(`${i}...`);
}
console.log('Selamat Hari Raya!');3...
2...
1...
Selamat Hari Raya!What changed? All three header parts flipped together — start high, test with >=, step down with i--. Change only one and the loop either runs forever or never runs at all.
Try It Yourself
13 minWork in kuih.js or a new loops.js. If a tab ever freezes, close it — you have written an infinite loop.
Task 1 — A times table
Print the 7 times table from 1 to 12, one line each, in the form
7 x 3 = 21. Use a template literal for the line.Task 2 — Even tables only
Print seating labels for tables 1 to 20, but mark the even-numbered ones as “window side”. Use
%and anifinside the loop.Then count how many window-side tables there were, and print that total.
Task 3 — Saving up
Aisyah saves RM 15 a week towards a RM 120 bicycle. Use a
whileloop to print each week and her running savings, stopping when she can afford it.Print how many weeks it took. Before you run it, say out loud what makes the loop end.
🔥 Mini-Challenge · The Loop That Never Ends
8 minDaniel wrote a queue counter. Do not run this — read it first. Find two mistakes.
// daniel-queue.js — buggy, do not run
let waiting = 5;
let served = 0;
while (waiting > 0) {
console.log('Serving customer ' + (served + 1));
served = served + 1;
}
for (let i = 1; i < 5; i++) {
console.log('Table ' + i + ' cleaned');
}
console.log('All 5 tables cleaned');It works if: five customers are served and the loop ends, and all five tables are reported cleaned.
Reveal the answer
Mistake 1 — an infinite loop.
The while tests waiting, but only served ever changes. waiting stays at 5 forever, so the loop never ends and the tab freezes. The line that moves things forward must change the value being tested.
Mistake 2 — an off-by-one loop.
i < 5 starting from 1 runs for 1, 2, 3, 4 — only four tables. The message then claims five. Either start at 0 and keep < 5, or start at 1 and use <= 5. Mixing the two is the classic off-by-one error.
// daniel-queue.js — fixed
let waiting = 5;
let served = 0;
while (waiting > 0) {
served = served + 1;
console.log(`Serving customer ${served}`);
waiting = waiting - 1; // the tested value now changes
}
const TABLES = 5;
for (let i = 1; i <= TABLES; i++) { // <= so table 5 is included
console.log(`Table ${i} cleaned`);
}
console.log(`All ${TABLES} tables cleaned`);Serving customer 1
Serving customer 2
Serving customer 3
Serving customer 4
Serving customer 5
Table 1 cleaned
Table 2 cleaned
Table 3 cleaned
Table 4 cleaned
Table 5 cleaned
All 5 tables cleanedNaming the count TABLES and using it in both the loop and the message means they can never disagree again.
Recap
3 min- A loop runs the same block many times, so you write it once.
- A
forheader has three parts: start, keep going while, after each pass. i++adds one;i--takes one away.- Counting from
0pairs with<; counting from1pairs with<=. - Declare a running total outside the loop.
whilesuits an unknown number of passes — but you must change the tested value.- An infinite loop freezes the tab. Always ask what makes it stop.
New words
- Loop — code that repeats.
- Iteration — one single pass through the loop.
- Counter — the variable tracking which pass you are on.
- Off-by-one — running one time too many or too few.
📦 Homework
4 min to brief · ~20 min to doRequired
- Write
stall.jsthat prints a numbered menu of 10 items using a loop, marks every fifth item as “chef's choice”, and prints the total cost at the end. - Add a comment above your loop saying, in your own words, what makes it stop. Bring the file next lesson.
Optional stretch
- Print a triangle of stars, one to five per line, using a loop inside a loop.
'*'.repeat(i)will help. - Look up
breakandcontinue. Write one sentence on what each does to a loop.