Skip to content
wannacode

Loops

Problem

How much will you save?

You decide to save money: the first month you put aside €10, the second €20, the third €30, and so on, €10 more each time. How much will you have after 4 months?

let total = 0;
total += 1 * 10;
total += 2 * 10;
total += 3 * 10;
total += 4 * 10;
console.log(total);
Output
100

It works. But after 3 years that is 36 lines, almost all the same. And if the number of months is typed on the keyboard, you have no idea how many lines to write. You need a way to say "repeat this so many times".

The idea

for: repeat while the condition is true

A piece of code that repeats is called a loop. The one you will use most is for. Here are the numbers from 1 to 10:

for (let i = 1; i <= 10; i++) {
console.log(i);
}
Output
1
2
3
4
5
6
7
8
9
10

The parentheses hold three parts, separated by ;:

  • Start: let i = 1. It runs once, before anything else. This is where the counter is created.
  • Condition: i <= 10. It is checked before every round. If it is true, the body runs. If not, the loop ends.
  • Step: i++. It runs after every round.

Each run of the body is called an iteration, or simply a round.

More precisely, if you are curious
  • The step can be whatever you need: i += 2 (every other number), i-- (backward).
  • The counter i exists only inside the loop. After the closing } it is gone, and if you use it, the program stops with ReferenceError: i is not defined.
  • You will often see counting from 0: for (let i = 0; i < 10; i++). It is still 10 rounds. Why you count from 0 will become clear in the lesson on arrays.

See it

Round by round

These are the savings from the first card, with a loop. Watch how month and total change.

let total = 0;
for (let month = 1; month <= 4; month++) {
total += month * 10;
}
console.log(total); // 100
Step by step, in words
  1. total starts at 0.
  2. month = 1. Check: 1 <= 4 is true, so we go into the body.
  3. Round 1: total += 1 * 10, total becomes 10.
  4. month++ makes month 2. 2 <= 4: one more round, total becomes 30.
  5. month 3: total becomes 60.
  6. month 4: total becomes 100.
  7. month++ makes month 5. 5 <= 4 is false: the loop ends.
  8. After the loop total is 100.

The body is one line, and it is written once. For 36 months you only change 4 to 36. You can even put a variable read from the keyboard there.

Try it

Countdown

What will the program print?

for (let sec = 3; sec > 0; sec--) {
console.log(sec);
}
console.log("Go!");
Answer

The idea

while: until the end comes

Sometimes you don't know ahead of time how many rounds there will be. The cash register reads prices until the cashier enters 0, and then it gives the total. for does not fit here. while does: just a condition, no start and no step.

let total = 0;
let price = Number(await ask(""));
while (price !== 0) {
total += price;
price = Number(await ask(""));
}
console.log(`Total: €${total}`);
rl.close();
Input
12
4
7
0
Output
Total: €23

Above the code are the lines for ask() from the lesson "Input and output". They are not shown here, but you need them, and rl.close() goes at the end.

The first price is read before the loop, so the condition has something to check. The next one is read at the end of the body. If the first number is 0, the body does not run even once.

If you want the body to run at least once, there is do-while. The condition is at the bottom and is checked after the round. It is handy for a question that repeats until the answer is acceptable:

let count;
do {
console.log("How many tickets (1 to 10)?");
count = Number(await ask(""));
} while (count < 1 || count > 10);
console.log(`Tickets booked: ${count}`);
rl.close();
Input
0
15
3
Output
How many tickets (1 to 10)?
How many tickets (1 to 10)?
How many tickets (1 to 10)?
Tickets booked: 3
More precisely, if you are curious
  • If the condition never becomes false, the loop never ends. This is an infinite loop: the program "hangs" and you have to stop it by hand. The most common cause is a forgotten change to the variable in the condition, for example a missing price = … at the end of the body.
  • After the while (…) of a do-while you write a ;. JavaScript adds it on its own if it is missing, but with it the code reads like Java and C#.
  • Any for can be written as a while, and the other way around. You pick the one that reads more clearly: for for a known number of rounds, while for "until something happens".

Try it

Find the bug

The program should add up the numbers from 1 to 5: 1 + 2 + 3 + 4 + 5 = 15. It prints 10. Which line has the bug?

Pick the line with the bug.

The idea

break and continue

Two words change the usual flow of a loop.

continue skips the rest of the current round and moves on to the next one. You are listing appointment times from 9 to 17, but 13 is the lunch break:

for (let hour = 9; hour <= 17; hour++) {
if (hour === 13) {
continue;
}
console.log(`${hour}:00`);
}
Output
9:00
10:00
11:00
12:00
14:00
15:00
16:00
17:00

break stops the whole loop right away. You are looking for the first number that 91 divides by. Once you find it, there is no point in going on:

const n = 91;
for (let d = 2; d < n; d++) {
if (n % d === 0) {
console.log(`${n} is divisible by ${d}`);
break;
}
}
Output
91 is divisible by 7
More precisely, if you are curious
  • break stops only the loop it is in. If it is in a nested loop (next card), the outer one keeps going.
  • You will often see while (true) with a break inside: a loop that ends not because of its condition, but because of a break in the right place.

The idea

A loop inside a loop

The movie theater has 3 rows of 4 seats. You want to print every seat. For each row you go through all the seats in it:

for (let row = 1; row <= 3; row++) {
let line = "";
for (let seat = 1; seat <= 4; seat++) {
line += `[${row}-${seat}]`;
}
console.log(line);
}
Output
[1-1][1-2][1-3][1-4]
[2-1][2-2][2-3][2-4]
[3-1][3-2][3-3][3-4]

These are called nested loops. The inner loop goes all the way through on every round of the outer one: 3 rows · 4 seats = 12 seats. console.log always moves to a new line, so the seats of one row are collected in the text line, and it is printed after the inner loop. For each row line starts over, empty.

Try it

Staircase

The first row should have one star, the second two, the fourth four. What goes in the blank?

for (let row = 1; row <= 4; row++) {
  let line = "";
  for (let star = 1; star <= ; star++) {
    line += "*";
  }
  console.log(line);
}

The idea

Random numbers for games

A dice game needs a number the program does not know ahead of time. Math.random() gives you one:

const dice = Math.floor(Math.random() * 6) + 1;
console.log(`Rolled ${dice}`);

Math.random() gives a decimal number from 0 to 1, not including 1, for example 0.7316…. Multiplied by 6, it is from 0 to 6 (not including 6). Math.floor drops the decimal part, which leaves a whole number from 0 to 5. With + 1 it becomes 1 to 6.

Each run gives a different number, so there is no output here. And here is a loop that rolls until it gets a six:

let rolls = 0;
let dice;
do {
dice = Math.floor(Math.random() * 6) + 1;
rolls++;
} while (dice !== 6);
console.log(`Six after ${rolls} rolls`);
More precisely, if you are curious
  • Math.random() does not take a starting number: Math.random(42) ignores the 42. A sequence that repeats on every run (handy for testing) needs a separate library.
  • The numbers are not truly random: they are computed with a formula. They are good enough for games, but not for passwords and security.

Exercise

Loop exercises

Solve the exercises in your editor. Each one has sample input and output to compare yours with. You read the number the same way as in the lesson "Input and output".

1. Multiplication table. Read a number and print its products with the numbers from 1 to 10.

Input
7
Output
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70

2. Prime number. A number is prime if it divides only by 1 and by itself: 2, 3, 5, 7, 11… Read a number and say whether it is prime. Hint: try the divisors from 2 up, and stop with break at the first one.

Input
91
Output
91 is not prime

For 11 the output is "11 is prime".

3. The digits of a number. Read a positive whole number. Print it reversed and the sum of its digits. Hint: n % 10 is the last digit, and Math.trunc(n / 10) drops the last digit. Repeat until the number becomes 0.

Input
2024
Output
Reversed: 4202
Sum of digits: 8

4. Guess the number. The computer "thinks of" a number from 1 to 100, and you look for it. After each guess the program says "It's lower." or "It's higher.", and at the end how many tries it took you. First write it with the secret number 37, so you can check it against the example:

Input
50
25
37
Output
It's lower.
It's higher.
You got it in 3 tries!

Once it works, replace 37 with a random number from 1 to 100. Now even you don't know the answer.

More exercises

  • From 1 to N. Read N and print the numbers from 1 to N on one line. For 5: 1 2 3 4 5.
  • Factorial. N! = 1 · 2 · 3 · … · N. For 5: 120. number keeps whole numbers exact only up to Number.MAX_SAFE_INTEGER (9007199254740991), and 20! is bigger (2432902008176640000). For big whole numbers JavaScript has BigInt: a number with n at the end, 1n, and BigInt(...) for what you read from the input.
  • Primes up to N. Print all prime numbers up to N. For 20: 2 3 5 7 11 13 17 19. The check from exercise 2 goes inside a loop over the numbers: nested loops.
  • Fibonacci. Each number is the sum of the two before it: 0, 1, 1, 2, 3, 5, 8… Read N and print the first N numbers. For 10: 0 1 1 2 3 5 8 13 21 34.
  • Square of stars. Read N and print an N × N square. For 3:
Output
* * *
* * *
* * *
  • Triangle of stars. The same, but each row has as many stars as its number. For 3:
Output
*
* *
* * *
  • Coin toss. Read N, toss a coin N times with a random number (0 is heads, 1 is tails) and print how many times each came up. The bigger N is, the closer both numbers get to N / 2.
  • Rock, paper, scissors. A player against the computer. The player types a choice, the computer picks at random, and the program says who wins. With do-while it asks "Another game? (yes/no)" and at the end prints the score.
More precisely, if you are curious

With a plain number, 22! no longer comes out exact, only as an approximation:

let result = 1;
for (let i = 2; i <= 22; i++) {
result *= i;
}
console.log(result);
console.log(Number.MAX_SAFE_INTEGER);
Output
1.1240007277776077e+21
9007199254740991

Test

Check yourself

1. How many times does the body of for (let i = 0; i < 5; i++) run?
2. What is the difference between while and do-while?
3. What does continue do?
4. The outer loop runs 3 times and the inner loop runs 4 times. How many times does the body of the inner loop run?
5. Which line gives a random number from 1 to 6?

Made by Ivo Gergov as part of Evo Tech's campaign for accessible programming education ·