ES5 changed variable object(VO) to lexical environment. What's the motivation of such change since VO is already very obvious as perception?
-
1I don't understand the question? What do you mean with `variable object`? Can you give a reference to the specification change that you're talking about? – nils Nov 11 '16 at 09:29
-
@nils added a link. – Thomson Nov 11 '16 at 09:43
-
2@MadaraUchiha Interesting, the ES3 spec actually did use the term `variable object`: http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf (Section 10.1.3) – nils Nov 11 '16 at 09:50
-
1I think this would be a great question to ask either Brendan Eich or Allen Wirfs-Brock on twitter, and write the answer here afterwards. – nils Nov 11 '16 at 10:11
-
See also [What really is a declarative environment record and how does it differ from an activation object?](https://stackoverflow.com/q/20139050/1048572) – Bergi Jul 29 '23 at 06:18
2 Answers
I think variable objects are more analogous to environment records.
An Environment Record records the identifier bindings that are created within the scope of its associated Lexical Environment.
In ES5 there are two different kinds of environment records:
Declarative environment records are used to define the effect of ECMAScript language syntactic elements such as FunctionDeclarations, VariableDeclarations, and Catch clauses that directly associate identifier bindings with ECMAScript language values. Object environment records are used to define the effect of ECMAScript elements such as Program and WithStatement that associate identifier bindings with the properties of some object.
So the question would be why declarative environment records were introduced instead of only using object environment records just like ES3 variable objects. The difference is that declarative environment records can have immutable bindings:
In addition to the mutable bindings supported by all Environment Records, declarative environment records also provide for immutable bindings. An immutable binding is one where the association between an identifier and a value may not be modified once it has been established.
Immutable bindings don't have a direct equivalent in objects. A property can be defined as both non-configurable and non-writable, becoming immutable. However,
Creation and initialisation of immutable binding are distinct steps so it is possible for such bindings to exist in either an initialised or uninitialised state.
But you can't have an uninitialized property. If you define a non-configurable non-writable property with value undefined, then you won't be able to initialize it to the desired value.
I don't think it's possible to have uninitialized immutable bindings in ES5. CreateImmutableBinding is only used in Declaration Binding Instantiation and Function Definition, and in both cases it's immediately initialized with InitializeImmutableBinding.
But possibly this was done to allow uninitialized immutable bindings as extensions of the language, like the JavaScript 1.5 const
. Or maybe they already had in mind ES6 const
.

- 274,082
- 63
- 437
- 513
The same author whose ES3 article you linked wrote also about ES5 (and even linked that section there). I'll quote Mr. Soshnikov from his "Declarative environment record" section in ECMA-262-5 in detail. Chapter 3.2. Lexical environments: ECMAScript implementation:
In general case the bindings of declarative records are assumed to be stored directly at low level of the implementation (for example, in registers of a virtual machine, thus providing fast access). This is the main difference from the old activation object concept used in ES3.
That is, the specification doesn’t require (and even indirectly doesn’t recommend) to implement declarative records as simple objects which are inefficient in this case. The consequence from this fact is that declarative environment records are not assumed to be exposed directly to the user-level, which means we cannot access these bindings as e.g. properties of the record. Actually, we couldn’t also before, even in ES3 — there activation object also was inaccessible directly to a user (except though Rhino implementation which nevertheless exposed it via
__parent__
property).Potentially, declarative records allow to use complete lexical addressing technique, that is to get the direct access to needed variables without any scope chain lookup — regardless the depth of the nested scope (if the storage is fixed and unchangeable, all variable addresses can be known even at compile time). However, ES5 spec doesn’t mention this fact directly.
So once again, the main thing which we should understand why it was needed to replace old activation object concept with the declarative environment record is first of all the efficiency of the implementation.
Thus, as Brendan Eich also mentioned (the last paragraph) — the activation object implementation in ES3 was just “a bug”: “I will note that there are some real improvements in ES5, in particular to Chapter 10 which now uses declarative binding environments. ES1-3’s abuse of objects for scopes (again I’m to blame for doing so in JS in 1995, economizing on objects needed to implement the language in a big hurry) was a bug, not a feature”.
I don't think I could express this any better.

- 630,263
- 148
- 957
- 1,375
-
I also thought something like this. But even if the spec used objects, implementations would be allowed to use whatever underlying data structures they want if the observable behavior is the same, wouldn't they? – Oriol Nov 12 '16 at 01:46
-
@Oriol Yeah, I guess they could, but it doesn't really fit, as records have a static shape (that's imo the most important difference). Then there's the creation vs. initialisation that you mention in your answer, and also lookup/assignment works quite different (prototype vs scope chains). – Bergi Nov 12 '16 at 11:01