Closures:

Vishal PandeyVishal Pandey
2 min read

1. First Loop (with differentScope function):

for(var i=1;i<=5;i++){
    const differentScope = (i)=>{
        setTimeout(()=>{
            console.log(i)
        },i*1000);
    }
    differentScope(i);
}

Output: 1 2 3 4 5 (each number printed at 1-second intervals)

Explanation:

  • We're using var for the loop variable i

  • Inside each iteration, we create a function differentScope that takes i as a parameter

  • We immediately call differentScope(i) with the current value of i

  • Because i is passed as a parameter to the function, it creates a new scope for each iteration

  • Each setTimeout gets its own copy of i from its scope

  • This works correctly, printing 1 through 5 at 1-second intervals

2. Second Loop (plain varwith setTimeout):

for(var i=1;i<=5;i++){
    setTimeout(()=>{
        console.log(i)
    },i*1000);
}

Output: 6 6 6 6 6 (each 6 printed at 1-second intervals)

Explanation:

  • We're using var which is function-scoped, not block-scoped

  • The loop completes before any setTimeout callback runs

  • By the time the callbacks execute, i has already reached 6 (the loop stops when i becomes 6)

  • All callbacks share the same i variable, which is now 6

  • The delays are still 1s, 2s, etc. because i*1000 is evaluated during the loop iteration

3. Third Loop (using let):

for(let i=1;i<=5;i++){
    setTimeout(()=>{
        console.log(i)
    },i*1000);
}

Output: 1 2 3 4 5 (each number printed at 1-second intervals)

Explanation:

  • We're using let which is block-scoped

  • In a for loop with let, a new binding is created for each iteration

  • Each setTimeout callback gets its own i from its respective iteration

  • This works correctly, printing 1 through 5 at 1-second intervals

Key Differences:

  1. The first loop works because we're passing i to a function, creating a new scope for each iteration.

  2. The second loop fails because var doesn't create a new binding for each iteration, and all callbacks share the same i.

  3. The third loop works because let creates a new binding for each iteration in a for loop.

This demonstrates why let is generally preferred in modern JavaScript for loop variables, especially when dealing with asynchronous operations inside loops.

0
Subscribe to my newsletter

Read articles from Vishal Pandey directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vishal Pandey
Vishal Pandey