Skip to content
JavaScript snippets

JavaScript Closure Inside Loops

Learn how JavaScript closures behave inside loops, why var causes repeated values, and how let, helper functions, and iteration methods solve the problem.

Published Updated

One of the most misunderstood concepts in JavaScript—especially for beginners—is closure behavior inside loops. If you’ve ever used a for loop and tried to run setTimeout or another asynchronous function inside it, only to get unexpected results, you’re not alone.

In this article, we’ll break down why closures behave the way they do inside loops, the difference between var and let, and how to fix common issues developers encounter.


📌 What is a Closure in JavaScript?

A closure is created when a function retains access to variables from its outer scope, even after that outer function has finished executing. Here’s a quick example:

function outer() {
  let count = 0;
  return function inner() {
    count++;
    return count;
  };
}

const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2

The function inner() is a closure because it “remembers” the variable count from its parent scope.


🔁 Closures in Loops: The Problem

Consider the following example using var inside a for loop:

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

Expected Output:

0
1
2

Actual Output:

3
3
3

Why? Because var is function-scoped, not block-scoped. All three closures inside the loop reference the same i, which after the loop ends, is 3.


✅ The Solution: Use let (Block Scope)

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

Output:

0
1
2

Using let creates a new scope for each iteration of the loop. Each setTimeout closure captures its own copy of i.


⚠️ Alternative Fix: IIFE (Immediately Invoked Function Expression)

Before let was introduced, developers used an IIFE to capture the current loop value:

for (var i = 0; i < 3; i++) {
  (function(j) {
    setTimeout(() => {
      console.log(j);
    }, 1000);
  })(i);
}

The IIFE creates a new function scope where j takes the current value of i, preserving it for the closure.


🧠 Best Practices


📚 Final Thoughts

Understanding how closures work inside JavaScript loops helps you avoid mysterious bugs and write more predictable, maintainable code. By using let or wrapping logic in closures (IIFEs), you ensure each iteration of your loop behaves the way you expect.

JavaScript closure inside loopsclosure in for loopJavaScript for loop closuresetTimeout loopvar vs let loop closureJavaScript scope inside loops