Nested Loops

JavaScript ECMAScript 2024 · ✓ verified by execution on 2026-08-10

When you place a loop inside another loop, you create a nested loop. This is an incredibly common and powerful technique used for generating combinations, working with grids, or traversing multi-dimensional arrays. While it might look confusing at first, the rule governing how they execute is straightforward and absolute.

For every single iteration of the outer loop, the inner loop must complete all of its iterations from start to finish.

How Nested Loops Execute

Let’s look at a basic example with two nested loops. Beginners often intuitively expect that loops run in parallel, or that they somehow advance together. In JavaScript, however, code execution is purely sequential.

javascript · visualize
for (let i = 1; i <= 2; i++) {
  for (let j = 1; j <= 3; j++) {
    console.log(`i=${i}, j=${j}`);
  }
}
i=1, j=1
i=1, j=2
i=1, j=3
i=2, j=1
i=2, j=2
i=2, j=3

Notice how the j loop completely counts from 1 to 3 while i is 1, and then does it all over again when i becomes 2:

Warning
Nested loops do not run in parallel. The inner loop acts as a roadblock; the outer loop cannot proceed to its next step until the inner loop has finished completely.

This behavior is fundamental to single-threaded JavaScript. The runtime cannot process the outer loop’s increment i++ until the entire block inside the outer loop has finished executing, which includes the entire lifecycle of the inner loop.

Working with 2D Arrays

A common use case for nested loops is iterating through a two-dimensional array (an array of arrays). Here, the outer loop selects a row, and the inner loop processes each column within that row.

javascript
const grid = [
  [1, 2], 
  [3, 4]
];

for (let i = 0; i < grid.length; i++) {
  for (let j = 0; j < grid[i].length; j++) {
    console.log(grid[i][j]);
  }
}
Output
1
2
3
4
row i col j
A grid traversed by nested loops: the outer loop selects a row, and for each row the inner loop runs across every column before the outer loop advances.

Breaking Nested Loops

Using break inside an inner loop only stops the inner loop. The outer loop will continue to its next iteration, completely unaffected by the inner loop’s early exit.

javascript
for (let i = 1; i <= 2; i++) {
  for (let j = 1; j <= 3; j++) {
    if (j === 2) break;
    console.log(`i=${i}, j=${j}`);
  }
}
Output
i=1, j=1
i=2, j=1

If you need to break out of both loops at the same time, you must use a labeled statement. This is one of the few places in modern JavaScript where labels are considered appropriate.

javascript
outer: for (let i = 1; i <= 2; i++) {
  for (let j = 1; j <= 3; j++) {
    if (j === 2) break outer;
    console.log(`i=${i}, j=${j}`);
  }
}
Output
i=1, j=1

The break outer; command tells JavaScript to exit the loop labeled outer, stopping both loops immediately.

The Scope Pollution Danger

If you forget to use let when initializing the inner loop variable, you will accidentally overwrite the outer loop’s variable. This is a very common source of infinite loops!

javascript
let count = 0;
for (let i = 0; i < 5; i++) {
  // Danger! We forgot 'let' here. This overwrites the outer 'i'.
  for (i = 0; i < 2; i++) {
    count++;
    if (count > 10) break; // Artificial limit
  }
  if (count > 10) break;
}
console.log(count);
Output
11

Because the inner loop resets i to 0, the outer loop will never reach 5, causing it to run forever unless artificially broken. The let keyword ensures the variable is scoped properly and independently.

What do you think will happen if the inner loop variable shadows the outer loop variable?

Predict the output javascript

Read the code. What exactly will it print? Commit to an answer before you look.

for (let i = 0; i < 2; i++) {
  for (let i = 0; i < 2; i++) {
    console.log(i);
  }
}
Output
0
1
0
1

Practice

Check yourself

When you have a nested loop, how does the inner loop execute relative to the outer loop?

Reveal answer

The inner loop completely finishes all of its iterations for every single iteration of the outer loop. — Nested loops execute sequentially. The inner loop must completely finish all of its iterations before the outer loop can proceed to its next iteration.

What happens if you use `break` inside an inner loop?

Reveal answer

It terminates only the inner loop, allowing the outer loop to continue. — A simple `break` statement only stops the innermost loop it resides in. The outer loop will continue its next iteration normally.

Why is it dangerous to forget `let` when initializing the inner loop variable (e.g. `for (i = 0; i < 5; i++)`)?

Reveal answer

It overwrites the outer loop's variable, causing logic bugs or infinite loops. — Without `let`, the inner loop modifies the exact same variable used by the outer loop, breaking the outer loop's progression and often causing infinite loops.

Challenges

Challenge 1 +20 XP

Write a nested loop that prints all coordinate pairs from `(0, 0)` up to `(1, 1)`. The outer loop should represent `x` (from 0 to 1) and the inner loop should represent `y` (from 0 to 1).

javascript
  • Test 1 — expects "(0, 0)\n(0, 1)\n(1, 0)\n(1, 1)"
Need a hint? (−25% XP)

Create an outer `for` loop for `x` and an inner `for` loop for `y`.

Show solution (0 XP)
for (let x = 0; x <= 1; x++) {
  for (let y = 0; y <= 1; y++) {
    console.log(`(${x}, ${y})`);
  }
}

🐞 Bug Hunt +30 XP

This code is supposed to log 'Hello' exactly 4 times (2x2), but it has a bug and runs forever. Fix the bug.

This code runs. It just does the wrong thing. Read it, find the defect, fix it — the tests below decide when you are right.

javascript
  • Test 1 — expects "Hello\nHello\nHello\nHello"
Need a hint? (−25% XP)

Check the initialization of the inner loop. Are you accidentally re-assigning the outer loop's variable?

Show solution (0 XP)
for (let i = 0; i < 2; i++) {
  for (let j = 0; j < 2; j++) {
    console.log('Hello');
  }
}