JavaScript Loops & Iteration
Master repetition structures, classic for loops, while/do-while mechanics, for...of vs for...in, break/continue control, and common loop traps.
1. What is a Loop?
A loop runs a block of code repeatedly, either a fixed number of times or until a condition stops being true. Without loops, printing numbers 1 to 100 would take 100 lines of manual code. With a loop, it takes just 3 lines.
💡 The 4 Essential Parts of Every Loop
1. Initialization: Where you start (e.g., let i = 0)
2. Condition: When to keep running (e.g., i < 5)
3. Body: The actual work done during each round
4. Update / Step: How you move forward (e.g., i++)
⚠️ If you forget the update step or your condition never becomes false, you create an infinite loop that freezes your browser tab!
2. The Classic for Loop
Use the classic for loop when you know in advance how many times to repeat, or when you specifically need the numeric index.
for (let i = 1; i <= 3; i++) {
console.log("Count:", i);
}
Count: 1 Count: 2 Count: 3
Execution Lifecycle:
let i = 1runs once at the start.- Condition
i <= 3is checked. If false, the loop exits. - If true, the loop body executes.
- Update
i++executes. - Jumps back to Step 2.
// 1. Counting backwards
for (let i = 5; i >= 1; i--) {
console.log("Countdown:", i);
}
// 2. Stepping by 2 (Even numbers)
for (let i = 0; i <= 6; i += 2) {
console.log("Even:", i);
}
// 3. Looping through an array by index
const colors = ["red", "green", "blue"];
for (let i = 0; i < colors.length; i++) {
console.log(`Index ${i}: ${colors[i]}`);
}
Countdown: 5 Countdown: 4 Countdown: 3 Countdown: 2 Countdown: 1 Even: 0 Even: 2 Even: 4 Even: 6 Index 0: red Index 1: green Index 2: blue
💡 The Off-By-One Bug Trap
Arrays are zero-indexed, meaning an array of length 3 has valid indices 0, 1, 2. Writing i <= arr.length instead of i < arr.length reads index 3, resulting in an unintended undefined value.
3. while vs do...while Loops
Use while loops when the number of iterations is unknown in advance and depends on a dynamic runtime condition.
while Loop (Pre-Condition)
Condition is checked before the body runs. May execute 0 times if condition is initially false.
let balance = 1000;
let years = 0;
while (balance < 2000) {
balance *= 1.07; // 7% growth
years++;
}
console.log(`${years} years to double`);
do...while Loop (Post-Condition)
Condition is checked after the body runs. Always executes at least once.
let attempts = 0;
do {
console.log("Attempt pass:", attempts);
attempts++;
} while (attempts < 1);
// Executes once even if false!
4. for...of (Values) vs for...in (Keys)
A foundational distinction tested in nearly every JavaScript technical interview:
for...of (Iterables & Values ✅)
Iterates directly over values of any iterable (Arrays, Strings, Maps, Sets).
- Gives element values directly
- Does not iterate inherited prototypes
- Best choice for Arrays
const fruits = ["Apple", "Banana"];
for (const fruit of fruits) {
console.log(fruit);
}
for...in (Object Keys ⚠️)
Iterates over enumerable property keys of an object and walks prototype chain.
- Gives keys as string types
- Leaches custom prototype properties
- Avoid on Arrays!
const user = { name: "Alex", age: 24 };
for (const key in user) {
console.log(key, "→", user[key]);
}
| Feature | for...of |
for...in |
|---|---|---|
| What it returns | Values | Keys / Property Names (Strings) |
| Works on | Iterables (Arrays, Strings, Maps, Sets) | Plain Objects |
| Includes prototype properties? | No | Yes (walks prototype chain) |
| Recommended for Arrays? | ✅ Yes | ❌ No |
Modern Way to Loop Over Objects: Use Object.entries() with for...of to get own properties safely without prototype issues:
const settings = { theme: "dark", fontSize: 16 };
for (const [key, value] of Object.entries(settings)) {
console.log(`${key} = ${value}`);
}
5. Controlling Loops: break, continue, and Labels
break immediately terminates the loop completely.
continue skips the rest of the current iteration and jumps directly to the next cycle.
for (let i = 1; i <= 6; i++) {
if (i === 2) continue; // Skips number 2
if (i === 5) break; // Exits loop when reaching 5
console.log("Number:", i);
}
Number: 1 Number: 3 Number: 4
Labeled Loops (Breaking Out of Nested Loops)
A standard break only exits the innermost loop. A labeled statement lets you break out of an outer parent loop directly from inside a nested loop:
outerLoop: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outerLoop; // Exits the entire outer loop!
}
console.log(`i=${i}, j=${j}`);
}
}
i=0, j=0 i=0, j=1 i=0, j=2 i=1, j=0
6. Common Loop Pitfalls & Solutions
Avoid these classic traps in coding rounds and production codebases:
1. The var Closure Bug ❌
var shares a single global/function binding across all timer callbacks.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Outputs: 3, 3, 3 (Shared!)
Fix with let Scope ✅
let creates a fresh block-scoped binding per iteration.
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Outputs: 0, 1, 2 (Preserved!)
⚠️ Do Not Modify Arrays While Looping
Using arr.splice(i, 1) inside a standard incrementing for loop alters the array indices, causing elements immediately following the removed item to be skipped. Instead, use arr.filter() or iterate backwards.
7. Decision Matrix: Which Loop Should I Use?
| Scenario | Best Loop Choice | Why |
|---|---|---|
| Fixed count / need numeric index | for (let i = 0; i < n; i++) |
Direct index access & control |
| Repeat until condition changes | while (condition) |
Evaluates before each cycle |
| Must execute at least once | do...while (condition) |
Evaluates after first cycle |
| Iterate Array or String values | for (const val of iterable) |
Direct value access, cleanest syntax |
| Iterate plain Object properties | for (const [k, v] of Object.entries(obj)) |
Safe, own-property iteration |
8. Loops Interview Deck
Test your understanding of loop execution order, off-by-one errors, for...of vs for...in, and loop control labels:
9. Practice Challenges
🎯 Coding Challenge: Loops & Iteration
1. Calculate the average of [88, 92, 79, 95, 85] using a for...of loop.
2. Iterate through { theme: "dark", notifications: true } using Object.entries() and print each key-value pair.