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 co开发者_开发问答nst x = 20?
in the above case, a() throws a reference error.
In the code you've provided, the x variable inside of the a() function is actually not the same x variable that is declared outside of the b() function. When a() is executed, it looks for the x variable in its own lexical environment, which is inside of the b() function. Since the x variable inside of the b() function is declared with the const keyword, it is in the temporal dead zone (TDZ) until it is initialized. Since a() is executed before the x variable is initialized, it tries to access the x variable and gets a reference error.
If you delete the const x inside of the b() function, then the x variable inside of a() will not be found in the b() function's lexical environment and will be looked for in the next outer lexical environment, which is the global environment. In the global environment, there is a x variable with the value 20, so it will console log 20.
In summary, when a function looks for a variable, it first looks in its own lexical environment. If it doesn't find the variable there, it looks in the next outer lexical environment, and so on until it reaches the global environment. If it still doesn't find the variable in the global environment, it will throw a reference error.
So to answer your question:
As for whether an inner function can "know" that a variable is in the TDZ, the answer is no. Inner functions can only access variables that are in the outer function's scope, and trying to access a variable that is in the TDZ will result in a ReferenceError, regardless of whether the variable is in the outer function's scope or not.
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.
First thing you cannot use const with the same variable it will give you an error because we cannot re-initialize const with the same variable name.
And I don't think that a() will give you a Reference error.
精彩评论