Reputation: 570
function b() {
function a() {
console.log(x);
}
a();
const x = 10;
}
const x = 20;
b()
If I understand lexical scoping and execution context correctly, when function a() is invoked, it should have a reference to b's lexical environment. During the execution of a(), the x const inside of b() is inside of the temporal dead zone until a finishes executing. However, shouldn't a() recognize that there is no x value to access (since it's in the TDZ) and thus should it not be searching through the global lexical environment to find that const x = 20?
in the above case, a() throws a reference error.
Upvotes: 3
Views: 129
Reputation: 50759
To explain what's happening internally, when b()
is called a new environment record (ER) is created. Conceptually, the "ER" represents a "scope" and is responsible for holding the bindings (variables) which are created within the b
function. The ER can have a binding created within it but no value associated with it, so a binding can be instantiated but not initialised to a value (due to this, the binding is in the TDZ). In the case of b
, an unitialised binding for x
is created within b
's ER before any of the code within b
has actually run. It is only once the code within b()
starts running and we reach the line const x = 10;
does the x
binding become initialized with a value. That means that even though you're calling a()
before the line const x = 10;
is evaluated, the x
binding has already been created, just without a value (this is why x
is "hoisted")
When you try and access x
from within a
, a
's scope (ie: its ER) is first checked for x
. As x
isn't defined within a
, we walk up the scope chain to the surrounding scope to search that for x
. As the surrounding scope is b
's scope, b
's ER is checked for the x
binding, which as explained above, it has. That's why we stop searching the scope chain when we check b
's scope, as we've already found a binding for x
, and thus we never check the global scope for its x
binding. However, as the binding for x
that we found within b
's ER has no value and is uninitialised, JavaScript will throw a ReferenceError.
Upvotes: 1