JavaScriptBeginner

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.

All JavaScript lessons

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:

  1. let i = 1 runs once.
  2. Is i <= 5? Yes, so run the body.
  3. Run i++. Now i is 2.
  4. 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 continue in while loops: make sure the update (like count++) happens before continue, 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 <= 5 runs 5 times starting from 1, but i < 5 runs only 4 times. For indexes, use i < length, never i <= length.
  • Infinite loops. Forgetting i++, or writing a condition that is always true.
  • Using const for the counter. It must be let.
  • Using the counter outside the loop. let i exists 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 continue before the update in a while loop. 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 < max still works, but max + 1 joins text. Convert it with Number().

Practice

  1. Print the numbers from 1 to 20 using a for loop.

  2. Print only the odd numbers from 1 to 20.

  3. Calculate the sum of all numbers from 1 to 50, and the sum of only the even ones.

  4. Print a countdown from 10 to 1, then print "Happy New Year!".

  5. Use a while loop to find how many times you can divide 1000 by 3 before the result drops below 1.

  6. Print this pattern using a nested loop:

    1
    12
    123
    1234
  7. Print the multiplication table of any number, but stop at the first result that is greater than 50 using break.

  8. Print the numbers 1 to 20, but skip the multiples of 4 using continue.

  9. Count how many times the letter "a" appears in "banana bread and apples".

  10. 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 be let.
  • while (condition) repeats while the condition is true. Best when the number of rounds is unknown.
  • do...while checks the condition after the body, so it always runs at least once.
  • break leaves the loop. continue skips to the next round.
  • Nested loops run the inner loop fully for each round of the outer loop.
  • Use i < length to walk through a string or an array, because indexes start at 0.
  • Avoid infinite loops (always change the condition’s variable) and off-by-one errors (< vs <=).
  • Next you will learn for...of and for...in, two easier ways to loop over lists, text and objects.