JavaScript Loops: for, while, do...while, break and continue
Learn how to repeat code in JavaScript with for, while and do...while loops, control them with break and continue, and avoid infinite loops and off-by-one bugs.
What you will learn
Imagine printing the numbers 1 to 100. You could write console.log() a hundred times, but that is boring and error-prone. A loop tells JavaScript: “Repeat this code as many times as needed.” In this lesson you will learn the for, while and do...while loops, how to stop or skip a repetition with break and continue, how loops can sit inside other loops, and how to avoid the two classic loop bugs.
Why do we need loops?
Without a loop:
console.log("Hello 1");
console.log("Hello 2");
console.log("Hello 3");
console.log("Hello 4");
console.log("Hello 5");
With a loop:
for (let i = 1; i <= 5; i++) {
console.log("Hello " + i);
}
Both print the same, but the loop version also works for 5,000 lines by changing one number. Loops are used for printing lists, adding up numbers, searching, repeating a task until it works, and much more.
The for loop
Use for when you know how many times to repeat.
for (let i = 1; i <= 5; i++) {
console.log("Number:", i);
}
Output:
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
The three parts
for ( start ; condition ; update ) {
// body: code to repeat
}
| Part | In our example | Meaning |
|---|---|---|
| Start | let i = 1 |
Runs once at the very beginning. Creates the counter. |
| Condition | i <= 5 |
Checked before every round. If true, the body runs. If false, the loop ends. |
| Update | i++ |
Runs after every round. Moves the counter forward. |
The order of events:
let i = 1runs once.- Is
i <= 5? Yes, so run the body. - Run
i++. Nowiis 2. - Back to step 2. Repeat until the condition is
false.
Here is the loop traced by hand:
| Round | i at start |
i <= 5? |
Prints | i after update |
|---|---|---|---|---|
| 1 | 1 | true | 1 | 2 |
| 2 | 2 | true | 2 | 3 |
| 3 | 3 | true | 3 | 4 |
| 4 | 4 | true | 4 | 5 |
| 5 | 5 | true | 5 | 6 |
| end | 6 | false | (stops) |
The name i is just a habit (short for index or iteration). You can use any name.
Counting down and in steps
// Countdown
for (let i = 5; i >= 1; i--) {
console.log(i);
}
console.log("Liftoff!");
// Even numbers up to 10 (steps of 2)
for (let i = 2; i <= 10; i += 2) {
console.log(i);
}
Why let and not const?
The counter changes every round (i++), and a const cannot change:
for (const i = 0; i < 3; i++) {
// TypeError: Assignment to constant variable.
}
The counter also lives only inside the loop. Outside it, it does not exist:
for (let i = 0; i < 3; i++) {
console.log(i);
}
console.log(i); // ReferenceError: i is not defined
Adding things up
Loops often keep a running total in a variable made before the loop:
let sum = 0;
for (let i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum); // 5050
The while loop
Use while when you do not know in advance how many rounds you need. It repeats as long as the condition is true.
let count = 1;
while (count <= 3) {
console.log("Count is", count);
count++;
}
Output:
Count is 1
Count is 2
Count is 3
You must create the variable before the loop and update it inside, or the loop never ends.
When while is better than for
How many times can you halve 100 before it drops below 1?
let value = 100;
let steps = 0;
while (value >= 1) {
value = value / 2;
steps++;
}
console.log(steps); // 7
How many digits does a number have?
let number = 12345;
let digits = 0;
while (number > 0) {
number = Math.floor(number / 10); // remove the last digit
digits++;
}
console.log(digits); // 5
How many years until savings of ₹10,000 double at 8% a year?
let balance = 10000;
let years = 0;
while (balance < 20000) {
balance = balance * 1.08;
years++;
}
console.log(`${years} years, balance ₹${Math.round(balance)}`);
// "10 years, balance ₹21589"
In none of these did we know the number of rounds beforehand. We only knew when to stop.
The do...while loop
do...while is like while, but the condition is checked after the body. So the body always runs at least once.
let n = 10;
do {
console.log("This runs once, even though n is not less than 5");
n++;
} while (n < 5);
Compare it with a normal while, which would run zero times in the same case:
let m = 10;
while (m < 5) {
console.log("This never runs");
}
Use do...while when you must do something first and then decide whether to repeat. A classic example is rolling a dice until you get a 6:
let roll;
do {
roll = Math.floor(Math.random() * 6) + 1;
console.log("Rolled:", roll);
} while (roll !== 6);
console.log("Finally a six!");
(The output is different each time. You will usually see a few numbers, then the 6.) Note the semicolon after while (...) in this loop.
break: stop the loop early
break ends the loop immediately, even if the condition is still true.
// Find the first number above 50 that is a multiple of 7
for (let i = 51; i <= 100; i++) {
if (i % 7 === 0) {
console.log("Found:", i); // 56
break;
}
}
Without break, the loop would keep checking all the way to 100. Use it when you already have your answer.
continue: skip one round
continue skips the rest of the current round and jumps to the next one.
// Print 1 to 10, but skip multiples of 3
for (let i = 1; i <= 10; i++) {
if (i % 3 === 0) {
continue;
}
console.log(i);
}
Output:
1
2
4
5
7
8
10
| What it does | |
|---|---|
break |
Leaves the whole loop |
continue |
Skips this round only and carries on |
Careful with
continueinwhileloops: make sure the update (likecount++) happens beforecontinue, or you will create an infinite loop.
Nested loops
A loop inside another loop is called a nested loop. The inner loop runs completely for every single round of the outer loop.
A star pattern
for (let row = 1; row <= 4; row++) {
let line = "";
for (let star = 1; star <= row; star++) {
line += "*";
}
console.log(line);
}
Output:
*
**
***
****
Row 1 gets one star, row 2 gets two stars, and so on. (A shorter version is "*".repeat(row), but the nested loop shows how they work.)
A multiplication grid
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
Be careful: 10 rounds outside × 10 rounds inside = 100 rounds in total. Nested loops can get slow when the numbers are large.
Looping over text and lists
You can use the counter as an index to visit every character of a string:
const word = "hello";
for (let i = 0; i < word.length; i++) {
console.log(i, word[i]);
}
Output:
0 h
1 e
2 l
3 l
4 o
Notice i < word.length (not <=). The last index is length - 1, because counting starts at 0.
The same idea works for arrays. An array is a list of values in square brackets. You will study arrays fully in a later lesson, but loops are the best way to see them in action:
const fruits = ["apple", "banana", "mango"];
for (let i = 0; i < fruits.length; i++) {
console.log(i, fruits[i]);
}
Output:
0 apple
1 banana
2 mango
In the next lesson you will meet for...of, a simpler way to loop over lists and text without managing an index.
Infinite loops
An infinite loop never stops, because its condition never becomes false. It will freeze your browser tab. The usual cause is forgetting to update the counter:
let i = 1;
while (i <= 5) {
console.log(i);
// forgot i++ -> i stays 1 forever!
}
(This is shown as plain text on purpose, so you do not run it by accident.)
How to avoid them:
- Check that something inside the loop changes the variable used in the condition.
- Check that the condition can actually become false.
- If a tab freezes while you are practising, close the tab and reopen the editor.
Real-life use cases
1. Factorial
5! = 5 × 4 × 3 × 2 × 1 = 120
const n = 5;
let factorial = 1;
for (let i = 2; i <= n; i++) {
factorial *= i;
}
console.log(`${n}! = ${factorial}`); // "5! = 120"
2. FizzBuzz (a famous interview question)
For 1 to 15, print “Fizz” for multiples of 3, “Buzz” for multiples of 5, “FizzBuzz” for both, and the number otherwise.
for (let i = 1; i <= 15; i++) {
if (i % 15 === 0) {
console.log("FizzBuzz");
} else if (i % 3 === 0) {
console.log("Fizz");
} else if (i % 5 === 0) {
console.log("Buzz");
} else {
console.log(i);
}
}
The i % 15 === 0 check goes first, because a multiple of 15 is also a multiple of 3 and 5. (Order matters, as you saw in the conditions lesson.)
3. Is a number prime?
A prime number can only be divided evenly by 1 and itself.
const number = 29;
let isPrime = number > 1;
for (let i = 2; i <= Math.sqrt(number); i++) {
if (number % i === 0) {
isPrime = false;
break; // no need to keep checking
}
}
console.log(`${number} is ${isPrime ? "prime" : "not prime"}`); // "29 is prime"
We only check up to the square root, because any divisor larger than that would have a partner smaller than it.
4. Count vowels in a sentence
const sentence = "Hello World";
let vowels = 0;
for (let i = 0; i < sentence.length; i++) {
const letter = sentence[i].toLowerCase();
if ("aeiou".includes(letter)) {
vowels++;
}
}
console.log(vowels); // 3
5. Reverse a string
const text = "JavaScript";
let reversed = "";
for (let i = text.length - 1; i >= 0; i--) {
reversed += text[i];
}
console.log(reversed); // "tpircSavaJ"
6. The first 10 Fibonacci numbers
Each number is the sum of the previous two: 0, 1, 1, 2, 3, 5, 8, ...
let a = 0;
let b = 1;
let output = "";
for (let i = 0; i < 10; i++) {
output += a + " ";
const next = a + b;
a = b;
b = next;
}
console.log(output); // "0 1 1 2 3 5 8 13 21 34 "
7. Times table
const table = 7;
for (let i = 1; i <= 10; i++) {
console.log(`${table} x ${i} = ${table * i}`);
}
8. Retry until it works (a while with break)
let attempts = 0;
const maxAttempts = 3;
while (true) {
attempts++;
console.log("Attempt", attempts);
const success = attempts === 3; // pretend it works on the third try
if (success || attempts >= maxAttempts) {
break;
}
}
while (true) loops forever on purpose, and the break is the only way out. Only write this if you are sure the break will be reached.
Which loop should I use?
| Situation | Best loop |
|---|---|
| I know the number of rounds (1 to 10, every item) | for |
| I repeat until something happens | while |
| I must run the code at least once | do...while |
Common mistakes
- Off-by-one errors.
i <= 5runs 5 times starting from 1, buti < 5runs only 4 times. For indexes, usei < length, neveri <= length. - Infinite loops. Forgetting
i++, or writing a condition that is always true. - Using
constfor the counter. It must belet. - Using the counter outside the loop.
let iexists only inside it. - A semicolon after the
for (...).for (let i = 0; i < 3; i++);makes an empty loop, and the block below runs only once. - Changing the counter inside the body by accident, such as
i++in the body as well as in the header. - Putting
continuebefore the update in awhileloop. The counter never moves, so the loop never ends. - Starting an array loop at 1. The first item is at index
0. - Doing heavy work inside nested loops. The number of rounds multiplies.
- Looping with a text number. If
max = "5"(text),i < maxstill works, butmax + 1joins text. Convert it withNumber().
Practice
-
Print the numbers from 1 to 20 using a
forloop. -
Print only the odd numbers from 1 to 20.
-
Calculate the sum of all numbers from 1 to 50, and the sum of only the even ones.
-
Print a countdown from 10 to 1, then print
"Happy New Year!". -
Use a
whileloop to find how many times you can divide1000by3before the result drops below1. -
Print this pattern using a nested loop:
1 12 123 1234 -
Print the multiplication table of any number, but stop at the first result that is greater than
50usingbreak. -
Print the numbers 1 to 20, but skip the multiples of 4 using
continue. -
Count how many times the letter
"a"appears in"banana bread and apples". -
Challenge: print all prime numbers from 1 to 50.
Recap
- A loop repeats code. It saves you from copying lines and works for any number of repeats.
for (start; condition; update)is best when you know the number of rounds. The counter must belet.while (condition)repeats while the condition is true. Best when the number of rounds is unknown.do...whilechecks the condition after the body, so it always runs at least once.breakleaves the loop.continueskips to the next round.- Nested loops run the inner loop fully for each round of the outer loop.
- Use
i < lengthto walk through a string or an array, because indexes start at0. - Avoid infinite loops (always change the condition’s variable) and off-by-one errors (
<vs<=). - Next you will learn
for...ofandfor...in, two easier ways to loop over lists, text and objects.