Loops let you repeat operations without writing the same code multiple times. JavaScript offers several loop constructs, each suited to different situations.
The for loop
The classic for loop has three parts in its header:
for (initialization; condition; update) {
// body runs each iteration
}
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
How it executes:
- initialization runs once before the loop starts (
let i = 0) - condition is checked before each iteration — if falsy, the loop stops
- body runs if the condition was truthy
- update runs after each iteration (
i++) - go back to step 2
The loop variable i is declared with let so it is scoped to the loop body. This prevents it from leaking into the surrounding scope.
Skipping and stopping
continue skips the rest of the current iteration and jumps to the next one:
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) continue; // skip even numbers
console.log(i); // 1, 3, 5, 7, 9
}
break exits the loop entirely:
for (let i = 0; i < 10; i++) {
if (i === 5) break;
console.log(i); // 0, 1, 2, 3, 4
}
The while loop
while repeats as long as a condition remains truthy:
let attempts = 0;
const maxAttempts = 3;
while (attempts < maxAttempts) {
console.log(`Attempt ${attempts + 1}`);
attempts++;
}
Use while when you do not know ahead of time how many iterations you need. The condition alone controls the loop.
// Read chunks until the stream is exhausted
let chunk = stream.read();
while (chunk !== null) {
process(chunk);
chunk = stream.read();
}
The do...while loop
do...while guarantees the body runs at least once, then checks the condition:
let input;
do {
input = prompt("Enter a number:");
} while (!input);
This is rarely used in practice because most loops can be written with while or for.
The for...of loop
for...of iterates over the values of an iterable (arrays, strings, maps, sets, and more):
const colors = ["red", "green", "blue"];
for (const color of colors) {
console.log(color); // "red", "green", "blue"
}
This is the cleanest way to iterate when you do not need the index. Under the hood, for...of uses the iterable protocol — it asks the collection for its next value until none remain.
When you need the index
Use .entries() to get both index and value:
const fruits = ["apple", "banana", "cherry"];
for (const [index, fruit] of fruits.entries()) {
console.log(`${index}: ${fruit}`);
}
// 0: apple
// 1: banana
// 2: cherry
for...in iterates keys, not values
for...in iterates over the property names of an object:
const user = { name: "Ada", age: 36 };
for (const key in user) {
console.log(key, user[key]);
}
// name Ada
// age 36
For objects, for...in is useful. For arrays, avoid it — it iterates over indices as strings and may include inherited properties:
const arr = ["a", "b", "c"];
for (const i in arr) {
console.log(typeof i); // "string" — indices are strings
}
Use for...of for arrays and for...in for plain objects.
Which loop to choose
| Situation | Best choice |
|---|---|
| Known number of iterations | for |
| Repeat until a condition changes | while |
| Iterate over array values | for...of |
| Iterate over object keys | for...in |
| Need index and value | for or for...of with .entries() |
| Transform or filter arrays | Array methods like .map() and .filter() (covered in the data manipulation unit) |
Common loop patterns
Accumulating a result
const numbers = [1, 2, 3, 4, 5];
let sum = 0;
for (const n of numbers) {
sum += n;
}
console.log(sum); // 15
Finding a match
const users = [
{ name: "Ada", active: true },
{ name: "Grace", active: false },
];
let found = null;
for (const user of users) {
if (user.active) {
found = user;
break;
}
}
console.log(found); // { name: "Ada", active: true }
Array methods like .find() handle this more concisely, covered in the data manipulation unit.
Building a new array
const numbers = [1, 2, 3, 4, 5];
const doubled = [];
for (const n of numbers) {
doubled.push(n * 2);
}
console.log(doubled); // [2, 4, 6, 8, 10]
Again, .map() replaces this pattern in modern code.
What to carry forward
foris best when you know the number of iterationswhileis best when you repeat until a condition changesfor...ofis the cleanest way to iterate array valuesfor...initerates object keys — avoid it for arrayscontinueskips to the next iteration;breakexits the loop- many traditional loop patterns have cleaner array-method equivalents
Loops handle repetition. The next unit covers functions, which handle reuse and organization.