let keyword in the for loop
squint's answer is no longer up-to-date. In ECMA 6 specification, the specified behaviour is that in
for(let i;;){}
i
gets a new binding for every iteration of the loop.
This means that every closure captures a different i
instance. So the result of 012
is the correct result as of now. When you run this in Chrome v47+, you get the correct result. When you run it in IE11 and Edge, currently the incorrect result (333
) seems to be produced.
More information regarding this bug/feature can be found in the links in this page;
Since when the let
expression is used, every iteration creates a new lexical scope chained up to the previous scope. This has performance implications for using the let
expression, which is reported here.
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.9CreatePerIterationEnvironment
.
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++;
…
for...of loop. Should I use const or let?
Why use
const
and when to uselet
infor...of
loops?
If there are no assignments to the identifier within the loop body, it's a matter of style whether you use let
or const
.
Use const
if you want the identifier within the loop body to be read-only (so that, for instance, if someone modifies the code later to add an assignment, it's a proactive error). Use let
if you want to be able to assign to it (because you have an assignment in your code, or you want someone to be able to add one later without changing the declaration).
You can do this with for-of
and for-in
loops. A for
loop's control variable is normally not constant (since in the normal case you update it in the "update" clause of the for
; if you don't, for
may be the wrong loop to use), so you normally use let
with it.
For clarity, here's an example with an assignment within the loop body:
for (let str of ["a", " b", " c "]) {
str = str.trim();
// ^^^^^----- assignment to the identifier
console.log(`[${str}]`);
}
Related Topics
JavaScript - Get the First Day of the Week from Current Date
Update Style of a Component Onscroll in React.Js
Get Client Time Zone from Browser
JavaScript Loop Through JSON Array
What Is the Order of Execution in JavaScript Promises
New Function()' with Lower Case "F" in JavaScript
Calling a JavaScript Function Named in a Variable
Why 'Null >= 0 && Null <= 0' But Not 'Null == 0'
Angularjs Changes Urls to "Unsafe:" in Extension Page
Getting Scroll Bar Width Using JavaScript
Convert Hh:Mm:Ss String to Seconds Only in JavaScript
How to Check If an Element Is Really Visible with JavaScript
What Is the Cleanest Way to Get the Progress of Jquery Ajax Request