Mastering Loops in JavaScript
break and continue, and how to avoid the dreaded infinite loop.
Why We Need Loops
Imagine you want to print the numbers 1 through 100. Without loops, you'd write console.log(1), console.log(2), all the way to console.log(100) — 100 separate lines. That's not just tedious, it's unmaintainable. What if the requirement changes to 1–1000?
Loops solve this by letting you describe what to repeat and when to stop. The JavaScript engine handles the repetition. This is one of the most fundamental ideas in all of programming: iteration.
for, while, do...while, for...of, and for...in. Each fits different scenarios.The for Loop
The for loop is the workhorse of JavaScript iteration. It packs initialization, condition, and update all into one concise line, making it easy to read when you know exactly how many times something should repeat.
let i = 0i < 5i++// Count from 1 to 5 for (let i = 1; i <= 5; i++) { console.log(`Count: ${i}`); } // Output: Count: 1, Count: 2, Count: 3, Count: 4, Count: 5 // Reverse countdown from 5 to 1 for (let i = 5; i >= 1; i--) { console.log(`T-minus ${i}...`); } console.log("Liftoff! 🚀");
let (not var) to declare your loop counter. With let, the variable only exists inside the loop block — cleaner, safer, and avoids subtle bugs in nested loops or async code.You can count by any increment — not just 1. Use i += 2 to step by twos, i *= 2 to double each time, or any expression you need. The update clause is just regular JavaScript.
The while Loop
The while loop is the right choice when you don't know in advance how many iterations you need. You simply provide a condition, and the loop keeps running as long as that condition is true. This is perfect for polling, waiting for user input, processing streams, or any scenario where the stopping point is dynamic.
// Simulating repeated input until valid entry let attempts = 0; let password = ""; while (password !== "secret123") { attempts++; // In a real app, this would prompt the user password = attempts === 3 ? "secret123" : "wrongpass"; console.log(`Attempt ${attempts}: ${password}`); } console.log(`Logged in after ${attempts} attempt(s)`);
false, the loop runs forever — freezing the browser tab. Always make sure something inside your while loop changes the condition variable. A good practice: add a max-iteration guard like if (count > 10000) break; during development.The key structural difference from for: initialization lives outside the loop, and the update step lives inside the loop body. This gives you more flexibility in where and how you modify the loop state.
The do...while Loop
The do...while loop is like a while loop with one crucial difference: it always executes the body at least once, then checks the condition. The condition check comes after the first run, not before.
This is ideal for menu systems, game loops, and any situation where you need to perform an action first and then decide whether to repeat it — like showing a menu option before asking if the user wants to continue.
// Menu system that always shows at least once let choice; let menuRuns = 0; do { menuRuns++; console.log("--- MENU ---"); console.log("1. Play Game"); console.log("2. View Scores"); console.log("3. Quit"); // Simulate user picking "Quit" on 2nd visit choice = menuRuns >= 2 ? "3" : "1"; console.log(`User chose: ${choice}`); } while (choice !== "3"); console.log("Goodbye!"); // Menu always shows on first run even if choice would be "3"
do...while. Classic examples: rendering a game frame, showing a welcome screen, processing the first item in a queue before deciding to continue.The for...of Loop
Introduced in ES6, for...of is the modern, clean way to iterate over iterable values — arrays, strings, Sets, Maps, and NodeLists. Instead of managing an index counter, you get each value directly. This is the loop you'll use most often in day-to-day JavaScript.
// Iterating an array of fruits const fruits = ["apple", "banana", "cherry", "mango"]; for (const fruit of fruits) { console.log(`I love ${fruit}!`); } // Output: I love apple!, I love banana!, ... // Iterating characters in a string const word = "code"; for (const letter of word) { console.log(letter.toUpperCase()); } // Output: C O D E // Get index with entries() for (const [index, fruit] of fruits.entries()) { console.log(`${index}: ${fruit}`); }
for...of when you only need the values. Use a classic for loop when you also need the index for something other than display, or when you need to modify the array in place by index. If you need both value and index, use entries() with destructuring as shown above.The for...in Loop
While for...of iterates over values, for...in iterates over the keys (property names) of an object. It's the standard way to walk through an object's enumerable properties when you need to inspect or transform them dynamically.
const player = { name: "Alex", level: 14, score: 4820, guild: "Dragon Riders" }; // Iterating over object keys for (const key in player) { console.log(`${key}: ${player[key]}`); } // Output: // name: Alex // level: 14 // score: 4820 // guild: Dragon Riders // Useful for dynamic property access const keys = []; for (const k in player) { if (typeof player[k] === "number") { keys.push(k); } } console.log("Numeric fields:", keys); // ["level", "score"]
for...in on an array iterates over index strings like "0", "1", "2" — plus any extra enumerable properties on the Array prototype. This is rarely what you want. Use for...of for arrays and for...in for plain objects.Loop Control: break & continue
Sometimes you need to jump out of a loop early or skip a specific iteration. JavaScript gives you two control statements for this: break exits the loop entirely, and continue skips the rest of the current iteration and jumps to the next one.
// break: find the first number divisible by 7 let found = null; for (let i = 1; i <= 100; i++) { if (i % 7 === 0) { found = i; break; // stop as soon as we find it } } console.log("First multiple of 7:", found); // 7 // continue: skip even numbers, print only odd for (let i = 1; i <= 10; i++) { if (i % 2 === 0) continue; // skip evens console.log(i); // 1, 3, 5, 7, 9 }
Nested Loops — Multiplication Table
Loops can be nested inside each other. The outer loop runs once, and for each outer iteration, the inner loop runs its full cycle. This is perfect for building 2D structures like grids or tables.
// 3x3 multiplication table for (let row = 1; row <= 3; row++) { let line = ""; for (let col = 1; col <= 3; col++) { line += `${row * col}\t`; } console.log(line); } // Output: // 1 2 3 // 2 4 6 // 3 6 9
Loop Comparison
| Loop Type | Best Used When | Knows Count? | Works On |
|---|---|---|---|
for |
You know the exact number of iterations | Yes | Anything |
while |
Stopping point is dynamic / condition-based | No | Anything |
do...while |
Must run at least once, then check | No | Anything |
for...of |
Iterating values in arrays, strings, Sets | Implicit | Iterables |
for...in |
Iterating keys of a plain object | Implicit | Objects |
break do inside a loop?for(let i=0; i<3; i++) console.log(i) print?continue do inside a loop?for loop to print all even numbers between 1 and 20 (inclusive). An even number is one where i % 2 === 0.Part 2: Rewrite the same logic using a
for...of loop. Create an array of numbers from 1 to 20, then filter for evens as you iterate.Bonus: Sum all the even numbers and log the total at the end.
Show hints
- For Part 1, use
if (i % 2 === 0) console.log(i)inside the loop body - For Part 2, create the array with
Array.from({length:20}, (_, i) => i + 1) - For the bonus, declare
let total = 0before the loop and add withtotal += i - Even numbers from 1–20: 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 — their sum is 110