Introduction
In two of my previous articles, I Know You Understand Hoisting, But Do You Really Understand It? and All Functions Are Closures: Discussing Scope and Closure in JS, I talked about the differences between the scopes of let and var.
The scope of let is block, while var is function. This is a classic example:
for(var i=1; i<=10; i++) {
setTimeout(function() {
console.log(i)
})
}
It was originally expected to output 1 to 10 in order, but unexpectedly output 10 11s. The reason behind this is that the i on the third line always has only one, which is the var i
declared in the for loop, and it is the same variable from beginning to end.
The classic solution is also very simple, just change var to let:
for(let i=1; i<=10; i++) {
setTimeout(function() {
console.log(i)
})
}
The reason why this works is that the above code can be seen as the following form:
{
let i=1
setTimeout(function() {
console.log(i)
})
}
{
let i=2
setTimeout(function() {
console.log(i)
})
}
...
{
let i=10
setTimeout(function() {
console.log(i)
})
}
Since the scope of let is block, there is actually a new i in each round of the loop, so there are 10 different i after the loop runs 10 times, and of course, 10 different numbers are output in the end.
Therefore, the biggest difference between var and let in this example is the number of variables, the former has only one, while the latter has 10.
Okay, now that you know the difference between let and var, let’s take a look at the main issue of this article.
In fact, this issue comes from a question raised by @getify, the author of YDKJS (You Don’t Know JS), on his Twitter:
question for JS engines devs…
is there an optimization in place for this kind of code?
for (let i = 0; i < 10; i++) {
}
IOW, where the behavior of creating a new i
per iteration is not needed nor observable… does JS skip doing it?
If you didn’t understand it very well, you can continue to read the other tweet:
here’s a variation on the question… will JS engines exhibit much performance difference between these two loops?
for (var i = 0; i < 100000000; i++) {
}
for (let i = 0; i < 100000000; i++) {
}
Simply put, when we usually use let with loops, isn’t it like we said above, there will be a new i
in each round? If so, then there should be a performance difference between var and let, because let must new a new variable in each round, so let will be slower.
If the loop does not need a new i in each round, will the JS engine optimize it? This issue is mainly to explore whether the JS engine will optimize this behavior.
So how do we know? Either you are a JS engine developer, or you can look at the JS bytecode, but both of these difficulties are a bit too high. But don’t worry, there is a third way: look at the JS bytecode.
Read More