Search code examples
javascriptecmascript-6ecmascript-2017

What is the difference between the specification types Environment Record (Lexical Environment) and Reference, in ECMAScript?


Reading the ECMAScript specification, it seems both an Environment Record (a component of a Lexical Environment), and a Reference is used to determine what variable / function an Identifier is bound to. In other words, finding the actual value represented by the Identifier.

I noticed that a Reference's Base value component can contain an Environment Record:

The base value component is either undefined, an Object, a Boolean, a String, a Symbol, a Number, or an Environment Record.

But, it is not clear to me when one would use a Reference instead of the execution context just reading an Environment Record straight out of the current Lexical Environment (as given by the running execution context's LexicalEnvironment component).


EDIT:

After accepting @Bergi 's answer, I wanted to add a couple of things I had not understood, in case it will help future readers:

  1. Identifier lookups in ECMAScript always returns a Reference type
    • To resolve a variable/function name, we start at 8.3.2 ResolveBinding
    • You will see that the running execution context's LexicalEnvironment (its Environment Record) is first checked
    • If no match is found, the Lexical Environment chain is followed outwards until a match (or not) is found
    • The chain ends at the global environment, which has an outer environment of null
    • Once a match is found, a Reference type is returned, which has its base value set to the value of the name in the Environment Record that matched
    • If no match is found, a Reference with a base value of undefined is returned
    • Thus, an identifier lookup always entails Environment Records being checked and a Reference type returned at the end
  2. Reference's GetValue is only ever done after evaluation of an Expression
    • GetValue(ref) is used on a Reference to return its base value
    • Searching the spec for "GetValue(", you will see that it only happens after evaluating an Expression of some kind
    • "Evaluating an Expression" means seeing what Reference an Expression returns
    • From this we can conclude that Expressions always evaluate to a Reference (a value)
    • Note: An Expression includes a wide range of other productions, such as IdentifierReference, which is deeply nested under the Expression production

Solution

  • An environment record is a record containing multiple variables.

    A reference is an object representing something mutable, like an object's property or a single variable.

    To find a value, like in console.log(value), you could just look up the name "value" in the current lexical environment and have the identifier evaluate to that. But to assign a value, like in value = 5, you need the identifier to evaluate to something that represents the location where the number can be stored - and that's the Reference type. It contains a base - the record (of the lexical environment) - and an identifier - the name of the particular variable. It can either be dereferenced to the value (GetValue), or you can assign a new value to it (PutValue).