Chapter 7 of 28 · JavaScript for Beginners — Complete Free Tutorial
Loops & Iteration
Repeating an action — processing a list, retrying a request, running a game frame — is a loop's job. JavaScript offers for, while, do…while, plus the modern for…of and for…in. Knowing which loop fits which job keeps your code short and bug-free.
for: the classic
for (let i = 0; i < 5; i++) {
console.log(`Iteration ${i}`);
}
// Expected output:
// Iteration 0
// Iteration 1
// … through Iteration 4
Three clauses: initialise (let i = 0), condition (i < 5 — checked before each run), update (i++ after each run). Using let scopes i to the loop, so it cannot leak out.
Counting patterns
// Down
for (let i = 10; i > 0; i--) console.log(i);
// Even numbers only (step by 2)
for (let i = 0; i <= 10; i += 2) console.log(i);
// Loop an array by index
const fruits = ['apple', 'mango', 'kiwi'];
for (let i = 0; i < fruits.length; i++) {
console.log(`${i}: ${fruits[i]}`);
}
Tip: cache fruits.length only if you mutate the array inside the loop; otherwise reading .length each pass is clearer.
while and do…while
// while: checks BEFORE running — may run zero times
let n = 5;
while (n > 0) {
console.log(n--);
}
// → 5 4 3 2 1
// do…while: runs at least ONCE, then checks
let attempts = 0;
do {
attempts++;
} while (attempts < 3);
console.log(attempts); // → 3
Rule: use while when the count is unknown up front (keep reading until a condition changes); use do…while for “run once, then maybe repeat” flows like menus.
break and continue
// break — leave the loop entirely
for (const n of [3, 8, 15, 4]) {
if (n > 10) break;
console.log(n); // → 3, 8 (stops at 15)
}
// continue — skip to the next iteration
for (const n of [3, 8, 15, 4]) {
if (n % 2 !== 0) continue; // skip odds
console.log(n); // → 8, 4
}
for…of: the modern default for lists
const scores = [88, 92, 75];
for (const score of scores) {
console.log(score);
}
for (const [name, role] of Object.entries({ ada: 'admin' })) {
console.log(`${name} = ${role}`); // → ada = admin
}
for…of works on any iterable: arrays, strings, Maps, Sets, NodeLists. It gives values directly — no index bookkeeping, no off-by-one errors. Use it for 90% of list work.
for…in: keys of an object
const user = { name: 'Asha', role: 'admin' };
for (const key in user) {
console.log(`${key}: ${user[key]}`); // → name: Asha, role: admin
}
Golden rule:
for…of→ values (arrays, strings).for…in→ enumerable keys (objects). Never usefor…inover an array — it yields string indices in an unpredictable order and picks up inherited properties.
Iterating without loop variables: forEach and array methods
[1, 2, 3].forEach((n) => console.log(n * 2)); // → 2 4 6
const doubled = [1, 2, 3].map((n) => n * 2); // → [2, 4, 6]
const big = [4, 9, 16].filter((n) => n > 5); // → [9, 16]
map/filter/reduce express what transformation happens instead of how to step through — the full toolkit is next in Arrays & Array Methods.
The infinite loop (and how to avoid it)
// ❌ i never changes — freezes the tab
for (let i = 0; i < 5; ) { … }
// ✅ always include a reachable exit
for (let i = 0; i < 5; i++) { … }
If a loop hangs, check that the condition eventually turns false. Browser dev tools offer a “Stop script” button and per-loop breakpoints to escape.
Loop performance, in one paragraph
Modern engines optimise all of these loops well. Only micro-optimise when profiling proves a hotspot; then prefer simple for loops over deeply chained method calls inside hot paths. Clarity first, speed when measured.
Common mistakes
- Off-by-one —
<vs<=decides whether the last element is included; arrays start at index 0. - Mutating an array while looping it — skipping elements; loop a copy (
[...arr]) or iterate backwards when removing. for…inover arrays — string keys, inherited props, order surprises.- Missing update — an accidental infinite loop.
varin loops — with async callbacks, every iteration shares one binding;letcreates a fresh one per pass (the famous timer bug in chapter 19).
Practice checklist
- Print the multiplication table for 7 (1–12) with a
forloop. - Find the first element over 100 in an array using
for…of+break. - Sum an array of numbers with a plain loop, then verify with
reduce. - Deliberately write an infinite loop, stop it with dev tools, then fix it.
Loops are the machinery — but functions are where programs get their structure. Next: Functions in JavaScript.
Frequently Asked Questions
JavaScript is the programming language of the web. It adds behaviour to pages: responding to clicks and input, validating forms, fetching data from APIs, updating the DOM without reloading, and much more. It also runs on servers (Node.js), in desktop and mobile apps, and in build tooling.
They are unrelated languages that share a similar name for historical marketing reasons. Java is a statically-typed compiled language; JavaScript is a dynamically-typed interpreted language designed for the browser. Knowing one does not imply knowledge of the other.
Helpful but not mandatory — HTML gives you the structure JavaScript manipulates and CSS the styling it toggles. If you know basic tags, classes and selectors, you have enough to start; the DOM chapters assume only that much.
Use const by default and let when the value must change. Avoid var entirely in modern code: it is function-scoped instead of block-scoped, hoists differently, and can create accidental globals. This course uses const and let throughout.
The Document Object Model is the browser’s in-memory tree of objects representing your HTML. JavaScript reads and modifies that tree — selecting elements, changing text, adding nodes, attaching event listeners — and the browser re-renders the page to match.
== compares after converting types (so 5 == "5" is true), while === requires the same value AND the same type (5 === "5" is false). Loose equality has famously confusing rules — use === and !== everywhere unless you have a specific reason not to.
JavaScript is single-threaded, so long-running work (timers, fetches, events) is handled by the browser and its callbacks are queued. The event loop moves queued callbacks onto the call stack only when it is empty, with promise callbacks (microtasks) taking priority over timers. It is why asynchronous code never freezes the page.
A Promise is an object representing a future value — pending, fulfilled or rejected — that can be chained and combined (Promise.all). async/await is syntax sugar over promises that lets asynchronous code read top-to-bottom with ordinary try/catch error handling.
Yes. Frameworks are built on exactly these fundamentals — components are functions, state is your variable discipline, effects are events, rendering is DOM work. Developers who learn vanilla first understand what the framework is doing and debug far faster.
Type out the examples instead of copying, build small end-to-end projects (expense tracker, weather app, quiz), handle every UI state (loading, empty, success, error), and revisit fundamentals while reading real code. Consistency beats volume — a little most days outpaces occasional marathons.