In the general case, declarative record bindings are supposed to be stored directly at a low implementation level (for example, in virtual machine registries, thereby providing quick access). This is the main difference from the old activation object concept used in ES3.
That is, the specification does not require (or even indirectly recommends) to implement declarative records as simple objects, which in this case are inefficient. The consequence of this fact is that declarative environment records are not supposed to be exposed directly to the user level, which means that we cannot access these relationships, for example, record properties. In fact, we could not even earlier, even in ES3, - the activation object was also inaccessible directly to the user (with the exception of the Rhino implementation, which, however, opened it through __parent__ ).
Potentially declarative entries allow you to use full lexical addressing , that is, get direct access to the necessary variables without any search in the chain of chains - regardless of the depth of the nested area (if the storage is fixed and unchanged, all address variables can be known even during compilation) . However, the ES5 specification does not mention this fact directly.
So, once again, the main thing that we must understand why it was necessary to replace the concept of the old activation object with a declarative record of the environment is, first of all, the effectiveness of implementation.
Thus, since Brendan Eih is also mentioned (last paragraph) - the implementation of the activation object in ES3 was just a โmistakeโ: I note that there are some real improvements in ES5, in particular in Chapter 10, which now uses declarative binding environments. ES1-3 abuses objects for regions (again, I was to blame for this in JS in 1995, saving on objects needed to implement the language in a big hurry) was a mistake, not a function. "
I do not think that I could express it better.