What is a Reference Record?

I'm reading https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-reference-record-specification-type. Document says left-hand operand of an assignment is expected to produce a Reference Record.
Is Reference Record part of Environment Record or something?

No, an Environment Record doesn’t contain Reference Records. The Environment Record contains variable bindings.

Reference Records can be references to those variable bindings in the Environment Record. In that case, they’re pointing to the bindings inside of the Environment Record.

Basically, variable references (like x) and property accesses (like x[y], x.a, and super.a) all evaluate into Reference Records. In contrast, other expressions like a number literal 42 or a function call x.a() do not evaluate into Reference Records.

Reference Records are usually invisible, because Reference Records usually turn into the values that they wrap. They are not invisible when they are the left-hand side of an assignment (as well as a couple of other operations like delete).

Imagine this:

const x = 5;
console.log(x); // Line A
x = 3; // Line B

What does x evaluate into, in Line A? What about in Line B?

In Line A, x gets evaluated into a Reference Record (a reference to the variable called x), and because the console.log function call needs the Reference Record’s value, the Reference Record gets “dereferenced” into 5.

In Line B, x gets evaluated into a Reference Record (a reference to the variable called x)…but the assignment operation does not dereference it into 5. It uses the name of the variable (which is in the Reference Record) to assign the new value 3.

In both lines, x evaluates into a Reference Record, but what happens to that Reference Record afterward depends on what operation it’s inside.

Most operations will dereference the value inside the Reference Record’s variable (or property chain or whatever). But assignment uses the name inside the Reference Record instead of dereferencing the Reference Record.

(In order to dereference a variable Reference Record, you need the variable’s name and the lexical environment that it’s from—its Environment Record. The variable’s name is stored in the Reference Record’s [[ReferencedName]] field, and the Environment Record that owns the variable is stored the Reference Record’s [[Base]] field.)

Now imagine this:

const x = 5;
console.log(x["a" + "b"]); // Line A
x["a" + "b"] = 3; // Line B

What does x["a" + "b"] evaluate into, in Line A versus Line B?
In both lines, x["a" + "b"] evaluates into a Reference Record for a property access. Its base is another Reference Record (for the variable called x) and its [[ReferencedName]] is "ab".
In Line A, that property-access Reference Record gets dereferenced by the console.log call into 5.
In Line A, that property-access Reference Record does not dereference the assignment operation; instead, the assignment operation uses the property-access Reference Record to figure out where to assign the new value 3.

In summary, a Reference Record is either:

  • A variable reference (in which case its [[Base]] is the current Environment Record and its [[ReferencedName]] is the name of the variable) or
  • A property access (in which case its [[Base]] is the base of the property access and its [[ReferencedName]] is the name of the property—a string, a #privateField, or a symbol).

I’m simplifying things, but this is how I think of them.

3 Likes

Thank you for your detailed description! helped a lot

1 Like