One of the key difference between let
and var
is:
Variables declared with var
or created by function declarations in non-strict mode do not have block scope. Variables introduced within a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope.
Explanation:
I will try to explain in simple words:
"Blocks are scoped to containing function or script" or block statements do not introduce a scope, means anything like below (which is a "block"):
{
StatementList
}
doesn't create its own scope (Block can be created by simply wrapping statements into curly braces).
Okay, lets see an example:
function foo()
{
var x = 1;
{
var x = 2;
}
console.log(x);
}
prints 2.
Function foo
has its own scope, but block doesn't. Hence the value changed or new declaration inside block statement(the curly braces outside of line var x = 2
creates new block) is persisted outside the block, i.e. in console statement.
However if we declare a variable x
again outside the function foo
it will be entirely different and will have its own scope.
suppose we have another function in same script block (or same module/file):
function xyz()
{
var x = 3;
console.log(x);
}
prints 3
What does this mean?, "It means functions create their own scope". So both x
one inside foo
and other inside xyz
are entirely different. Changing one would have effect only inside its own function scope.
Now let
What var
is for two different functions, let
is for two different blocks. So every block creates its own scope for let
.
So if I changed my function foo
to:
function foo()
{
let x = 1;
{
let x = 2;
}
console.log(x);
}
prints 1
This means the block inside function has its own scope, and the var x
is entirely different from the one outside.
What happens with loop?
It creates different block for each iteration, so loop can be expanded like below:
/*---------Block 1------------*/
{
let i = 0;
//... other loop statments
arr.push(function(){
return i;
});
}
/*----------Block 2-----------*/
{
let i = 1;
//...
arr.push(function(){
return i;
})
}
/*--------- Block 3------------*/
{
let i = 2;
//...
arr.push(function(){
return i;
})
}
Now we see, all three let
are having their own scope which is introduced by the pair of curly braces we have for each iteration of loop, but in case of var
it will be single scope irrespective of how many blocks we create.
As variable i
is not immediately used in block but its used inside a function which creates its own scope and will take the value from its outer scope, in case of var
outer scope is only one (which would have final value of i
i.e. 3) but in case let
there are 3 outer scope, hence each will have its own value.
Reference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block
For the other differences between var
and let
:
https://stackoverflow.com/a/11444416/1421196