Reputation: 643
Hey so i've been reading lately the ecmascript spec and i've encountered a talk about LexicalEnvironment and VariableEnvironment
like
- Let oldEnv be the running execution context's LexicalEnvironment.
- Let blockEnv be NewDeclarativeEnvironment(oldEnv).
- Perform BlockDeclarationInstantiation(StatementList, blockEnv).
- Set the running execution context's LexicalEnvironment to blockEnv.
- Let blockValue be the result of evaluating StatementList.
- Set the running execution context's LexicalEnvironment to oldEnv.
- Return blockValue.
right the LexicalEnvironment now points to the blockEnv which is a declarative Environment Record
but it doesn't says at what place we are searching for variables.
based on logic i assume it's searching inside the LexicalEnvironment.
what i'm asking is where can i find the rule that's says the place where we are looking for variables and functions.
Upvotes: 2
Views: 159
Reputation: 1074809
The scope chain is implemented via the [[OuterEnv]] property of environment objects.
Every Environment Record has an [[OuterEnv]] field, which is either null or a reference to an outer Environment Record. This is used to model the logical nesting of Environment Record values. The outer reference of an (inner) Environment Record is a reference to the Environment Record that logically surrounds the inner Environment Record.
Basically, when looking up the binding for an identifier, the current environment object is used, and if no matching binding is found, the one linked via [[OuterEnv]] is used, and so on.
You can see that in ResolveBinding which uses GetIdentifierReference. If GetIdentiferReference on doesn't find the binding on the environment object it's called with, it calls itself recursively with that environment's [[OuterEnv]]:
In a comment you asked why we need VariableEnvironment. We have both VariableEnvironment and LexicalEnvironment (and GlobalEnvironment, for that matter), which are all environment record objects (1, 2). We need variable environment vs. lexical environment in order to handle var
-scoped declarations differently from lexically-scoped declarations (let
, const
, etc.). For example:
function example() {
// Here, the LexicalEnvironment and the VariableEnvironment
// are the same environment record; let's call it "outer"
var a = 1; // Created in "outer"
{
// Here, there's a new environment set as the LexicalEnvironment,
// using "outer" as its [[OuterEnv]. Let's call it "inner". See
// https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation
var b = 2; // Created in "outer"
let c = 3; // Created in "inner"
console.log(typeof a); // "number", found in "outer"
console.log(typeof b); // "number", found in "outer"
console.log(typeof c); // "number", found in "inner"
}
console.log(typeof a); // "number", found in "outer"
console.log(typeof b); // "number", found in "outer"
console.log(typeof c); // "undefined", not found at all
}
example();
Upvotes: 2