I know the difference between let and var. let is block scope and var is functional scope.
for(var i=0; i< 3; i++){
setTimeout(function(){
console.log(i);
}, 10);
}
output : 3
3
3
I know how above code snippet is working(console.log(i)
is executing at that time when value of i is 3, because scope of i is global).
But
for(let i=0; i< 3; i++){
setTimeout(function(){
console.log(i);
}, 10);
}
output : 1
2
3
the above code snippet confusing me. according to me it should throw Reference Error(because the time when console.log(i)
execute, will look the value of i in global scope not in local scope, and i is not declare/defined in global. so it should give reference error.)
Anyone who can explain how 2nd for loop working on Runtime ?
let is block-scoped. var is function scoped. let does not allow to redeclare variables. var allows to redeclare variables.
In terms of performance comparison, var is faster and let is slower inside the loops while running or executing the code. Re-declaring var declared a variable in the same function or scope gives rise to Syntax Error whereas let declared variable cannot be redeclared.
let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
Use let when you know that the value of a variable will change. Use const for every other variable. Do not use var.
The second example (using let
) works because a function will close over all variables that are in scope when it is declared. Each iteration of the for loop a new variable is being created with let
, the function in the timeout closes over the variable and keeps a referance. When the function is dereferenced after the timeout, so are its closure variables.
See How do JavaScript closures work for more information on function closure.
This is the magic of closure. In side your loop
for(let i=0; i< 3; i++){
setTimeout(function(){
console.log(i);
}, 10);
}
you are declaring a function
function(){
console.log(i);
}
Additionally, the loop itself declares a block
for(let i=0; i< 3; i++){
// this is a block scope because it is contained in
// braces
}
Variables defined with let
are block scoped.
Because of closure, the function you declare inside the loop has access to all the variables declared in its scope and its parents scopes until it is garbage collected.
A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time that the closure was created.
The variable i
is in-scope when the functions used by setTimeout
are created. The i
referred to is a different instance of i
for each iteration of the loop.
The function exists until the interval you declared passes. That is why each of the 3 functions declared in your loop print the value of i
; it was declared in the containing scope and remains available to the function.
When you use let
in this context, a new binding/scope is created at each iteration. If you want to achieve a similar behavior in ES5 with var
, you have to use an IIFE:
for (var i = 0; i < 3; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, 10);
})(i);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With