Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

191
Views
Behavior of let variables declared inside for loop in context of closures

In below snippet, the function passed to setTimeout forms a closure with the variable i which is present in the script scope. So the function contains a reference to variable i. The value of i is updated to 5 before i is logged to console. And the output is: 5 5 5 5 5 (with newlines)

script.js:

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

The above part is clear to me. But when I declare variable i inside for loop, then i is block scoped to the for loop.

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

In this code snippet, I expect the output to be same as output of first snippet, because the closure contains reference to the variable i and the value at that reference should be updated to 5 before the value is logged to console. But the actual output is: 0 1 2 3 4 (with newlines)

The question is, why the code in second snippet behaves this way?

It it because:

  1. A new copy of variable i is created in memory for each iteration of for loop and previous copy is garbage collected? I'm not sure how memory management works for loops.
  2. Instead of storing reference of i, the value of i is stored in closure? I don't think this is the case.
  3. Anything else?

Please help to clarify. Thanks!

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

Your question mentions a few implementation details. Yet, these implementation details don't matter when answering your question.

You are indeed right, that there is some specific behavior of the for-loop occurring. Let's look at the ECMAScript 2021 standard here:

When your for-loop with let is evaluated, these steps are performed first:

enter image description here

Steps 4, 9 and 10 are particularly interesting to us. Step 4 gathers all const and let variables declared in the for-loop.

Step 9 sets perIterationLets to the let variables (if there are let variables) or to the empty list otherwise. Step 10 then calls ForBodyEvaluation to actually run the loop:

enter image description here

Here, let's focus on 3.e and take a closer look at CreatePerIterationEnvironment:

enter image description here

Carefully following the invocation hierarchy, we note that perIterationBindings is the list perIterationLets of let variables we gathered before.

In lines e.i, e.ii, e.iii, we now create a new binding (think of this as the memory location where the variables lives) and copy the value of the variable with the same name from the previous iteration into it. It is a different new variable though, even if it has the same name!

Thus if a closure inside a loop body captures the current context, the loop variables will not change, because each loop body iteration has its own current context.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!