/* Hoisting exampe - let */
let a = 100;
{
console.log(a); // 100
}
{
console.log(a); // ReferenceError: a is not defined
let a = 50;
}
/* Hoisting took place in {}. */
{
let a=100;
console.log(a); // 100
}
console.log(a); // ReferenceError: a is not defined
First, I know that let
andconst
have a block scope.
Compilation happens in Execution context units, and hoisting occurs when LexicalEnvironment
is created.
And the execution context is created by the execution of global, function, eval code.
Shouldn't hoisting of const
andlet
be done in global, function, eval code units?
(It seems that hoisting doesn't seem to happen, but this is purely thanks to the help of TDZ. Internally both const and let hoisting.)
If engine meet block {/* code */}
(rather than function) while creating Execution Context, are engine adding a new scope for the block to [[Scope]]
?
When a block is first encountered (with the {
), a new execution context is created, which creates a new empty Lexical Environment (which is basically a container mapping variable names in the current immediate scope to their values). The engine then iterates through all variables declared with const
or let
in the immediate block are initialized. (But, despite being initialized, they aren't referenceable until the engine actually comes across the const <variableName>
or let <variableName>
line - the TDZ)
So, plain blocks do create a new scope, which will get populated if any statements immediately inside that block declare a variable with const
or let
.
You can see this in action with a debugger:
/* Hoisting took place in {}. */
{
debugger;
let a=100;
console.log(a); // 100
}
console.log(a); // ReferenceError: a is not defined
Result in Chrome devtools:
(though, that's a bit misleading - a
doesn't actually contain undefined
, it hasn't been fully created at that point)
The const
and let
variable names are hoisted in that the interpreter recognizes from the start of the block that it'll be illegal to reference them until they get fully created via the const
or let
line.
It's not just plain blocks - any level of code will result in the same sort of thing happening (like at the top level, or inside a for
block, or inside a function).