Declare variables in loop initializer statements
Read today to see the following sentences:
In Depth ES6 chapter 1, block-level scoped binding, described in the let declaration section of the loop on page 9
Each iteration of the loop creates a new variable and initializes it with the value of the variable of the same name from the previous iteration.
It is also mentioned in Chapter 3 of JavaScript Advanced Programming (4th edition), Language Basics, Section 3.3.2, page 28
When you declare iteration variables using let, the JavaScript engine declares a new iteration variable behind the scenes for each iteration loop.
Best practices
for
Recommended for use in loopslet
To declare the iteration variablefor... in
andfor... of
It is recommended to useconst
To declare the iteration variable.
It’s kind of hard to see why we’re doing this, so let’s write some code to try it out.
Code practice
1. Asynchronous printing
for (var i = 0; i < 3; ++i) {
setTimeout(() = > {console.log(i)})
}
Copy the code
Output 3, 3, 3
Reason: Var declarations promote variables. The function refers to I in the global scope, and by the time I is printed, the value of I has changed to 3.
Let’s do that
for (let i = 0; i < 3; ++i) {
setTimeout(() = > {console.log(i)})
}
Copy the code
Output 0, 1, 2
Reason: Each iteration of the loop creates a new variable I in its block-level scope.
ES5
for (var i = 0; i < 3; ++i) {
(function (i){
setTimeout(() = > {console.log(i)})
}(i))
}
Copy the code
Output 0, 1, 2
Cause: An artificial copy of I was made using closures.
2. Create functions in the loop
var fns = []
for (var i = 0; i < 3; ++i) {
fns.push(() = > { console.log(i) })
}
fns.forEach(fn= > fn())
Copy the code
Output 3, 3, 3
Reason: Var declarations promote variables. The function uses the same I in the global scope. When printing I, the value of I has changed to 3.
Let’s do that
var fns = []
for (let i = 0; i < 3; ++i) {
fns.push(() = > { console.log(i) })
}
fns.forEach(fn= > fn())
Copy the code
Output 0, 1, 2
Reason: Let creates a new variable I for each loop, and three functions refer to three different I.
ES5
var fns = []
for (var i = 0; i < 3; ++i) {
(function (i) {
fns.push(() = > { console.log(i) })
}(i))
}
fns.forEach(fn= > fn())
Copy the code
Output 0, 1, 2
Reason: Using the nature of function scope, variable I is artificially copied in each loop.
Loop through using reference type variables
for (const i = {a: 0}; i.a < 3; i.a = i.a + 1) {
i[`${i.a}`] = i.a
setTimeout(() = > console.log(i), 1000 * i.a)
}
// { '0': 0, '1': 1, '2': 2, a: 3 }
// { '0': 0, '1': 1, '2': 2, a: 3 }
// { '0': 0, '1': 1, '2': 2, a: 3 }
Copy the code
Reason: The I copied by the JavaScript engine in each loop is actually an address to the heap memory object.
Since we are only changing the value of the heap object property, we are not changing the value of I (which is actually a pointer to the heap object), we can declare I using const, which gives the same result as we did with let and var.
If JavaScript provided an API to view the memory address of the variable stack, it would be easy to verify this statement.