Explanation of 'Let' and Block Scoping With For Loops

Explanation of `let` and block scoping with for loops

Is this just syntactic sugar for ES6?

No, it's more than syntactic sugar. The gory details are buried in §13.6.3.9
CreatePerIterationEnvironment.

How is this working?

If you use that let keyword in the for statement, it will check what names it does bind and then

  • create a new lexical environment with those names for a) the initialiser expression b) each iteration (previosly to evaluating the increment expression)
  • copy the values from all variables with those names from one to the next environment

Your loop statement for (var i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); desugars to a simple

// omitting braces when they don't introduce a block
var i;
i = 0;
if (i < 10)
process.nextTick(_ => console.log(i))
i++;
if (i < 10)
process.nextTick(_ => console.log(i))
i++;

while for (let i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); does "desugar" to the much more complicated

// using braces to explicitly denote block scopes,
// using indentation for control flow
{ let i;
i = 0;
__status = {i};
}
{ let {i} = __status;
if (i < 10)
process.nextTick(_ => console.log(i))
__status = {i};
} { let {i} = __status;
i++;
if (i < 10)
process.nextTick(_ => console.log(i))
__status = {i};
} { let {i} = __status;
i++;

JavaScript: Understanding let scope inside for loop

General Explanation

When you use let in the for loop construct like you show, there is a new variable i created for each invocation of the loop that is scoped just to the block of the loop (not accessible outside the loop).

The first iteration of the loop gets its value from the for loop initializer (i = 1 in your example). The other new i variables that are created each loop iteration get their value from the i for the previous invocation of the loop, not from the i = 1 which is why they aren't all initialized to 1.

So, each time through the loop there is a new variable i that is separate from all the other ones and each new one is initialized with the value of the previous one and then processed by the i++ in the for loop declaration.

For your ES6 code of this:

for(let i = 1; i <= 5; i++) {

setTimeout(function(){

console.log(i);

},100);

}

Explanation of `let` and block scoping with for loops

Is this just syntactic sugar for ES6?

No, it's more than syntactic sugar. The gory details are buried in §13.6.3.9
CreatePerIterationEnvironment.

How is this working?

If you use that let keyword in the for statement, it will check what names it does bind and then

  • create a new lexical environment with those names for a) the initialiser expression b) each iteration (previosly to evaluating the increment expression)
  • copy the values from all variables with those names from one to the next environment

Your loop statement for (var i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); desugars to a simple

// omitting braces when they don't introduce a block
var i;
i = 0;
if (i < 10)
process.nextTick(_ => console.log(i))
i++;
if (i < 10)
process.nextTick(_ => console.log(i))
i++;

while for (let i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); does "desugar" to the much more complicated

// using braces to explicitly denote block scopes,
// using indentation for control flow
{ let i;
i = 0;
__status = {i};
}
{ let {i} = __status;
if (i < 10)
process.nextTick(_ => console.log(i))
__status = {i};
} { let {i} = __status;
i++;
if (i < 10)
process.nextTick(_ => console.log(i))
__status = {i};
} { let {i} = __status;
i++;

Explanation of `let` and block scoping with for loops

Is this just syntactic sugar for ES6?

No, it's more than syntactic sugar. The gory details are buried in §13.6.3.9
CreatePerIterationEnvironment.

How is this working?

If you use that let keyword in the for statement, it will check what names it does bind and then

  • create a new lexical environment with those names for a) the initialiser expression b) each iteration (previosly to evaluating the increment expression)
  • copy the values from all variables with those names from one to the next environment

Your loop statement for (var i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); desugars to a simple

// omitting braces when they don't introduce a block
var i;
i = 0;
if (i < 10)
process.nextTick(_ => console.log(i))
i++;
if (i < 10)
process.nextTick(_ => console.log(i))
i++;

while for (let i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); does "desugar" to the much more complicated

// using braces to explicitly denote block scopes,
// using indentation for control flow
{ let i;
i = 0;
__status = {i};
}
{ let {i} = __status;
if (i < 10)
process.nextTick(_ => console.log(i))
__status = {i};
} { let {i} = __status;
i++;
if (i < 10)
process.nextTick(_ => console.log(i))
__status = {i};
} { let {i} = __status;
i++;



Related Topics



Leave a reply



Submit