17

Okay, so I lately have been reading about ES-5 lexical environment scope and I am not sure if I really understand what is going on with how variables are stored in EcmaScript. I did some research but it didn't clarified my information, only brought me up to two questions. So there they are:

  1. The first one is about ES-3 activations objects/variable objects. After reading ES-3 Specification and some sources on the Internet I can assume that they are just normal object, for example like those created by new Object, but none of the sources says "yes, this is just a plain object" directly. Moreover, Dmitry Soshnikov wrote on his blog (the emphasis is mine):

    Schematically and for examples, it is possible to present variable object as a normal ECMAScript object

    and that quotation doesn't let me be sure about what really an activation object is. So this is the first question: is an activation object a regular EcmaScript object? If not, then what is it otherwise?

  2. In ES-5 we now have object environment records, which seem to be more or less the same that ES-3 activation objects, and declarative environment records, which replaced activation objects in functions and try-catch statement. So, assuming that object environment records are just plain EcmaScript objects, then what is a declarative environment record? The specification doesn't clarify this, furthermore, from what I've read there I cannot imagine that this is not implemented as an object. So, again, if declarative environment records are not ES objects, then what are they and how are they implemented and represented during the code execution?

Thank you very much in advance for brightening that topic for me.

EDIT: I think I need to clarify what is this question about. The main thing that I want to know is what is the exact difference between activation objects/object environment records and declarative environment records. That's what I'm interested in most.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Kuba Jagoda
  • 4,908
  • 2
  • 19
  • 21
  • 1
    *"how are they implemented and represented during the code execution"* That depends on the engine and the language the engine is written in. It is not further specified in the specification because it is an implementation detail. – Felix Kling Nov 22 '13 at 07:11
  • @FelixKling okay, so I understand that replacing activation objects with declarative environments records is nothing more than just giving the engines a free will on how they want to store variables? – Kuba Jagoda Nov 22 '13 at 07:15
  • 1
    That was always the case. Let me put it this way: If you were writing a JavaScript engine in JavaScript, you'd probably use JS objects to implement "object environment records" and "declarative environment records". All that the engine requires is a map or container to store information. In JavaScript itself you'd probably use an object, in PHP an associative array and in Python a dictionary. Using a JS object is just an example to make the abstract concept of "object environment records" more concrete. Does this make sense? – Felix Kling Nov 22 '13 at 07:24
  • @FelixKling and now the first part of my question comes in: does it mean, that before declarative environments record were introduced to ES, engines were forced to store variables in plain JavaScript objects? I just need a confirmation or denial on that, this is the last missing element of that puzzle for me. – Kuba Jagoda Nov 22 '13 at 07:32
  • That's what my comment tried to explain. They have never been JS objects. You could think about them *as* JS objects, because they map something to something else, just like JS objects do. – Felix Kling Nov 22 '13 at 07:44
  • But this is essentially what my question is about: if declarative environment records are implementation-and-engine dependent objects, then what are activation objects/object environment records and how they differ from declarative environment records, if none of them are pure ES objects? – Kuba Jagoda Nov 22 '13 at 07:51
  • I'm working on an answer btw :) – Felix Kling Nov 22 '13 at 08:22
  • You are too fixated on JavaScript objects, because of Dmitry's statement. I highlight the key points: *"**Schematically** and for examples, it is possible to **present** variable object as a normal ECMAScript object"*. That means, to make the concept of the variable object easier to imagine, you can think about it as a JavaScript object. Why? Because a JavaScript is basically a map of `property names -> property values`. A variable object is a map of `variable name -> variable value`. Since both are Maps, you can *represent* one through the other. Anything that can be treated as a Map [...] – Felix Kling Nov 22 '13 at 08:57
  • [...] could represent a variable object. But it seems that using a JavaScript object to visualize these concepts confused you more than it helped. – Felix Kling Nov 22 '13 at 08:58
  • 1
    See also [Why variable object was changed to lexical environment in ES5?](https://stackoverflow.com/q/40544709/1048572) – Bergi Jul 29 '23 at 06:17

1 Answers1

37

First of all you have to be aware that all of these terms just describe concepts. They don't dictate any kind of implementation. But because this can be hard to imagine/visualize it can be helpful to think about these concepts as instantiations of something you know, like maps or tables.

Declarative environment records (DER) and object environment records (OER) have one thing in common: They are both environment records (ER), which are defined in the specification as:

An Environment Record records the identifier bindings that are created within the scope of its associated Lexical Environment.

This basically means that an ER keeps track of variable and function names and their associated values.

Consider this example:

var foo = 42;
function bar() { };

The corresponding ER would have two entries, one for foo and one for bar. If you imagine an ER to be a table, then it would look like

  name        value
----------------------
  foo          42
  bar    <function object>

Now on to the difference between DER and OER. A DER might be the easiest to understand.

Declarative Environment Record

The term declarative should sound familiar since we are often talking of variable declarations and function declarations. The specification says:

Each declarative environment record is associated with an ECMAScript program scope containing variable and/or function declarations. A declarative environment record binds the set of identifiers defined by the declarations contained within its scope.

So, when you see

var foo = 42;

or

function bar() {

}

then you can assume that their names and values are stored in a DER.

Object Environment Record

OERs are less common, but in each JS application there exist at least one OER. The specification describes it as

Each object environment record is associated with an object called its binding object. An object environment record binds the set of identifier names that directly correspond to the property names of its binding object.

Have you ever wondered why the properties of the window object are global variables? That's because the ER of the global scope is an OER: window is the binding object and for each of its properties a corresponding entry is created in the OER. This is also in the specification:

The global environment’s Environment Record is an object environment record whose binding object is the global object.

Here is an example: Lets assume out binding object is

var obj = {
   answer: 42
};

then the OER would be

    name        value
------------------------
    answer       42

Note that in this case, the binding object (obj) is really a JavaScript object. You are in the same situation when you are using the with statement:

var obj = { foo: 42; };

with (obj) {
    foo = foo / 2;
}

console.log(obj);

with creates a OER and populates it with the property names and values from the passed object. That's why you can access them without explicitly referring to them via obj.*. The OER also makes sure to update the binding object with the new value if one was assigned to one of the identifiers.


Activation Object

It looks like that in ES3, activation objects (AO) where automatically created when a function was executed and it was holding a reference to the special arguments object. This seems to be related to DERs, but still to be something independent.
The concept of AOs doesn't seem to exist anymore in ES5 and I assume that it was unnecessary, since arguments can be added directly to the DER of the execution context.

Execution Context

A new execution context (EC) is established whenever a function is executed and is used to keep track of the state of the execution:

An execution context contains whatever state is necessary to track the execution progress of its associated code.

This means the engine can add whatever information it needs to track the execution progress. But the specification also defines components that an EC must have, one of which is the VariableEnvironment, which is an ER (probably always a DER, but I don't know for sure). That means an ER is a part of an EC.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 3
    Great answer, I do appreciate the effort. So that means the main (and only) difference between DER and OER is that OER always has a pure JS object attached to it, which is its "binding object"? – Kuba Jagoda Nov 22 '13 at 09:16
  • 2
    That's how I understand it. There are some things that still find confusing as well, e.g. are variable declarations in global scope also stored in the OER? Probably, because they become properties of the global object. But I haven't found a definite answer to that yet, and I didn't want to make it more confusing. – Felix Kling Nov 22 '13 at 09:19
  • Also: you said, that activation object is rather equivalent of execution context than OER. But the ES-3 specification says: "When control enters an execution context for function code, an object called the activation object is created and associated with the execution context. The activation object is initialised with a property with name arguments and attributes { DontDelete }". This is what suggested me that AO is a pure ES object, and now I really don't know what is the difference between storing variables in ES-3 and in ES-5, except the naming. – Kuba Jagoda Nov 22 '13 at 09:21
  • Oh I see. Then it looks like the AO was just removed from the specification. Because it simply says about `arguments`: *"When control enters an execution context for function code, an arguments object is created"*. So previously it was a property of the AO and now it's just created (like any other variable, function argument). I will update my answer. – Felix Kling Nov 22 '13 at 09:26
  • Now I only need to find out what activation object was. Because I still understand it as a pure ES object (its properties had normal properties attributes ({DontDelete} in the arguments example), like in a regular object - doesn't it suggest that it was a regular object? Because for me it does). It's going to be a tough task, since AOs aren't used anymore, but the curiosity is killing me :) – Kuba Jagoda Nov 22 '13 at 09:48
  • 1
    I don't think it's a normal JS object. It's still just a *concept*. But anyways, I can also ask at work tomorrow to get some more info about this. – Felix Kling Nov 22 '13 at 09:57
  • I'd really appreciate that. Let me know, if you find out something on the topic. – Kuba Jagoda Nov 22 '13 at 10:52
  • That's interesting for me. Why we need OER? For example Global Environment can use DER. Why OER added? – Murad Sofiyev Aug 21 '19 at 19:23