Loops repeat code: once for each item in a list, a set number of times, or until something changes. JavaScript has several kinds of loop, and choosing the right one makes code shorter and safer. This lesson covers each loop, how to stop or skip, and which loop suits arrays and objects.
The for loop
The classic for loop counts. It has three parts in its brackets, separated by semicolons:
for (let i = 1; i <= 3; i++) {
console.log(`Round ${i}`);
}
// Round 1
// Round 2
// Round 3
- Initialisation,
let i = 1, runs once before the loop starts. - Condition,
i <= 3, is checked before every pass. The loop stops when it is false. - Update,
i++, runs after every pass.
Use let for the counter, not const, because it changes. The counter only exists inside the loop.
A for loop can walk through an array by index. Arrays start at index 0, so the condition is i < length, not <=:
const colours = ["red", "green", "blue"];
for (let i = 0; i < colours.length; i++) {
console.log(`${i}: ${colours[i]}`);
}
// 0: red
// 1: green
// 2: blue
Getting the boundary wrong by one, an off-by-one error, is one of the most common bugs in programming. That is a big reason to prefer for...of for arrays.
for…of: loop over values
for...of gives you each value of an array, or any other iterable such as a string, in turn. There is no counter to get wrong:
const colours = ["red", "green", "blue"];
for (const colour of colours) {
console.log(colour);
}
// red
// green
// blue
You can use const here because each pass creates a fresh variable. This is the loop to reach for first whenever you need every item of an array.
It works on strings too, one character at a time:
for (const letter of "Hi!") {
console.log(letter);
}
// H
// i
// !
If you also need the index, use the array's entries() method with destructuring, which lesson 23 explains in full:
for (const [index, colour] of colours.entries()) {
console.log(`${index + 1}. ${colour}`);
}
// 1. red
// 2. green
// 3. blue
Later in the course you will meet NodeLists of page elements, Maps and Sets. for...of works on all of them. Lesson 44 explains the iteration protocol that makes this possible.
for…in: loop over object keys
for...in loops over the property names (keys) of an object:
const course = { title: "JavaScript", lessons: 54, level: "beginner" };
for (const key in course) {
console.log(`${key}: ${course[key]}`);
}
// title: JavaScript
// lessons: 54
// level: beginner
The course[key] syntax reads a property whose name is held in a variable. Lesson 13 covers it.
Avoid for…in on arrays
for...in works on arrays, but it gives you keys, and keys are always strings:
const scores = [10, 20];
for (const i in scores) {
console.log(i, typeof i);
}
// 0 string
// 1 string
That leads to bugs such as i + 1 giving "01". for...in can also pick up extra properties that have been added to an array or inherited from elsewhere. Use for...of for arrays and keep for...in for plain objects.
Even for objects, many developers prefer Object.keys() or Object.entries() with for...of, which only include the object's own properties. Lesson 24 covers those methods.
while: loop until a condition changes
A while loop repeats as long as its condition is true. Use it when you do not know in advance how many passes you need:
let balance = 100;
let months = 0;
while (balance > 0) {
balance -= 30;
months++;
}
console.log(`Paid off in ${months} months`);
// Paid off in 4 months
The condition is checked before every pass, so if it starts out false, the body never runs.
Infinite loops
If the condition never becomes false, the loop never ends. In a browser, the tab freezes because JavaScript cannot do anything else while the loop runs:
// Do not run this
let count = 0;
while (count < 5) {
console.log(count);
// Forgot count++
}
Make sure something inside every while loop moves it towards its end. If you do freeze a tab, close it; the browser will eventually offer to stop the script.
do…while
A do...while loop checks its condition after each pass, so the body always runs at least once:
let attempts = 0;
do {
attempts++;
console.log(`Attempt ${attempts}`);
} while (attempts < 2);
// Attempt 1
// Attempt 2
It is rarely needed, but it suits "do something, then decide whether to repeat".
break and continue
break leaves a loop immediately. Use it when you have found what you were looking for:
const orders = [12, 45, 230, 18];
for (const total of orders) {
if (total > 100) {
console.log(`First large order: ${total}`);
break;
}
}
// First large order: 230
continue skips the rest of the current pass and moves on to the next:
const names = ["Ada", "", "Grace", ""];
for (const name of names) {
if (name === "") {
continue;
}
console.log(name);
}
// Ada
// Grace
Both work in for, for...of, for...in, while and do...while loops. Use them sparingly; a loop with several break and continue statements becomes hard to follow.
Building up a result
A common pattern is to start with an empty or zero value and update it on each pass:
const prices = [4.5, 12, 3.25];
let total = 0;
for (const price of prices) {
total += price;
}
console.log(total);
// 19.75
const words = ["learn", "build", "ship"];
const shouted = [];
for (const word of words) {
shouted.push(word.toUpperCase());
}
console.log(shouted);
// ["LEARN", "BUILD", "SHIP"]
These patterns are so common that arrays have built-in methods for them, such as map(), filter() and reduce(). Lesson 22 covers them, and you will often use them instead of a loop. Loops remain the right choice when you need break, when you work with something that is not an array, or when a plain loop is simply clearer.
Which loop to use
| You want to | Use |
|---|---|
| Go through every item of an array, string or other iterable | for...of |
| Count, or step through numbers in a pattern | for |
| Repeat until a condition changes | while |
| Go through the keys of a plain object | for...in, or Object.keys() with for...of |
| Transform or filter an array into a new one | Array methods (lesson 22) |
Summary
forloops count, with an initialisation, a condition and an update. Watch for off-by-one errors.for...ofgives you each value of an array or other iterable, and is the default for arrays.for...ingives you an object's keys as strings. Do not use it on arrays.whilerepeats as long as a condition is true; make sure something ends it.breakleaves a loop;continueskips to the next pass.- Building a result in a loop is common, and array methods often do it more neatly.