james
james

Reputation: 570

Does the inner function know that a variable is inside the temporal dead zone before searching further through the scope chain?

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

Answers (1)

Nick Parsons
Nick Parsons

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

Related Questions