6

Could someone clarify what the difference is between these two, as they exist in the Execution context? It's hard for me to read the ECMA 262 v 5 specification and clearly see the difference.

Thank You,

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
contactmatt
  • 18,116
  • 40
  • 128
  • 186

2 Answers2

9

Both are components (of the same type) of Execution Contexts, but they serve distinct purposes (from the spec):

LexicalEnvironment

Identifies the Lexical Environment used to resolve identifier references made by code within this execution context.

VariableEnvironment

Identifies the Lexical Environment whose environment record holds bindings created by VariableStatements and FunctionDeclarations within this execution context.

The next paragraph explains why they need to be different:

When an execution context is created its LexicalEnvironment and VariableEnvironment components initially have the same value. The value of the VariableEnvironment component never changes while the value of the LexicalEnvironment component may change during execution of code within an execution context.

That does not happen often and usually both refer to the same Lexical Environment. A good example for a changing LexicalEnvironment is given in the question Why do catch clauses have their own lexical environment? - see §12.14. The other place I could find in the spec where this happens are With Statements (§12.10) where an Object Environment Record is dynamically used for the identifier resolution - yet variable/function declarations are static.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Where is the `LexicalEnvironment` and `VariableEnvironment` stored in memory? Typically, primitive values like numbers, boolean, etc are stored on the call stack, while others things like objects are stored in the heap. When a function is popped off the stack, the memory assigned to that function is cleared from the stack and the references to the objects are garbage collected. But if it returns a function, then that memory must be preserved to maintain closure. So are these variables copied from call stack to memory heap when a function returns a function? – darKnight Jan 24 '23 at 20:19
  • @darKnight "*Typically, primitive values like numbers, boolean, etc are stored on the call stack, while others things like objects are stored in the heap*" - what makes you think that? You can consider the variable environments to be objects that might be referenced from closures. Then, JS engines apply crazy optimisations where they can. If you care about the concrete memory layout, you'd need to study a particular JS engine in detail (and its different optimisation stages, which likely treat things differently). – Bergi Jan 24 '23 at 21:56
4

As far as I understand, those are just different names used to refer to the same type of entity (Lexical Environment). They have different names due to different purposes.

LexicalEnvironment is used to resolve identifiers while VariableEnvironment is used to declare variables and functions.

Both of them reference Lexical Environment (= Environment Record + optional outer Lexical Environment; aka scope chain) that's created for each execution context.

The LexicalEnvironment and VariableEnvironment components of an execution context are always Lexical Environments. When an execution context is created its LexicalEnvironment and VariableEnvironment components initially have the same value. The value of the VariableEnvironment component never changes while the value of the LexicalEnvironment component may change during execution of code within an execution context

Example in pseudo code:

// VariableEnvironment (global) = { __outer__: null }
// LexicalEnvironment = VariableEnvironment (global)

(function foo() {

  // VariableEnvironment (A) = { x: undefined, __outer__: global }
  // LexicalEnvironment = VariableEnvironment (A)

  var x;

  (function bar(){

    // VariableEnvironment (B) = { y: undefined, __outer__: A }
    // LexicalEnvironment = VariableEnvironment (B)

    var y;

    x = 2;

    // VariableEnvironment (A) = { x: 2, __outer__: global }
    // LexicalEnvironment is still the same as VariableEnvironment (B)

  })();

})();
kangax
  • 38,898
  • 13
  • 99
  • 135
  • You and Bergi seem to have different interpretations of "the value of the LexicalEnvironment component may change". Please correct me if you're wrong, but you seem to be talking about changes in the value of a component of a Lexical Environment (e.g., with variable assignment), while Bergi's answer is about cases where the whole LexicalEnvironment object is replaced. Now I'm confused! – bfavaretto Mar 01 '13 at 19:28
  • I don't think we have different interpretations. But looking at my example, I can see how it might have been confusing. Sorry :) Variable assignment certainly doesn't change anything about LexicalEnvironment. I just wanted to show that VE changes from one function context to another, while LE — most of the time — is just a reference to current VE. What @Bergi mentioned about `catch` and `with` is correct. Those are two cases when LE and VE reference different environments (there's no need for new VE in `with` and `catch`; only new LE — to be able to resolve additional identifiers) – kangax Mar 01 '13 at 19:48
  • Thanks for clarifying. You're right, the assignment line and the two comments after it were the source of my confusion. Maybe you should remove them from the example, if I may suggest. – bfavaretto Mar 01 '13 at 20:11