0

In the function below, Does LexicalEnvironment’s [[outerEnv]] refer to the VariableEnvironment(the VariableEnvironment which belongs to the same Execution Context).

Or LE,VE are same and their [[outerEnv]] both refer to global EnvironmentRecord?

function fun(){
  let a = 1
  var b = 2
}
  • "*refer to the VariableEnvironment*" - to **which** VariableEnvironment? – Bergi Dec 08 '21 at 18:44
  • @Bergi Thank you, I have read many of your other [answers](https://stackoverflow.com/questions/69417158/how-will-the-lexical-environment-and-the-variable-environment-will-look-like-at/69419481#69419481) and benefited from them. I draw a [picture](https://imgpp.com/image/ZXOuI) to describe my question. – 用户17435438 Dec 09 '21 at 03:31

1 Answers1

0

TL;DR: Inside a function, [[VariableEnvironment]] and [[LexicalEnvironment]] both point to the same Environment Record, whose [[outerEnv]] points to the Environment Record inside which the function was created.


The [[VariableEnvironment]] internal property of an Execution Context points to the corresponding function scope, that is, the scope in which var and function declarations create their Bindings.

On the other hand, [[LexicalEnvironment]] points to the current block scope. That is where Bindings created by let, const, class, catch and with statements exist, and from where Binding lookups happen.

A new [[LexicalEnvironment]] is generated for each block, while there's only one [[VariableEnvironment]] created for an Execution Context.

On the topmost scope of functions (which have their own Execution Contexts), these two are the same, and indeed, they point to the same Environment Record. You can see this in PrepareForOrdinaryCall, which is evaluated before a function is called:

10.2.1.1 PrepareForOrdinaryCall ( F, newTarget )

The abstract operation PrepareForOrdinaryCall takes arguments F (a function object) and newTarget (an Object or undefined). It performs the following steps when called:

  1. Let callerContext be the running execution context.
  2. Let calleeContext be a new ECMAScript code execution context.
  3. Set the Function of calleeContext to F.
  4. Let calleeRealm be F.[[Realm]].
  5. Set the Realm of calleeContext to calleeRealm.
  6. Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
  7. Let localEnv be NewFunctionEnvironment(F, newTarget).
  8. Set the LexicalEnvironment of calleeContext to localEnv.
  9. Set the VariableEnvironment of calleeContext to localEnv.
  10. Set the PrivateEnvironment of calleeContext to F.[[PrivateEnvironment]].
  11. If callerContext is not already suspended, suspend callerContext.
  12. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  13. NOTE: Any exception objects produced after this point are associated with calleeRealm.
  14. Return calleeContext.

Emphasis mine

The [[outerEnv]] property of that Environment Record points to the [[Environment]] of the function, which is the Environment Record where the function was constructed.

The [[outerEnv]] of an Environment Record that is the [[LexicalEnvironment]] of an inner block, points to the Environment Record of the block it's inside of.

So, in your case, it would look like this:

+-----------------------------+
|    fun Execution Context    |
+-----------------------------+
|                             |        +----------------------+
|  [[LexicalEnvironment]] -----------> |  Environment Record  |
|                             |        +----------------------+
|  [[VariableEnvironment]] ----------> |                      |
|                             |        |  bindings: [         |
+-----------------------------+        |    a = 1,            |
                                       |    b = 2             |
                                       |  ]                   |
                                       |  [[outerEnv]] --+    |
                                       |                 |    |
                                       +-----------------|----+
+-----------------------------+                          |
|  Global Execution Context   |                          | 
+-----------------------------+                          v
|                             |        +----------------------+
|  [[LexicalEnvironment]] -----------> |  Environment Record  |
|                             |        +----------------------+
|  [[VariableEnvironment]] ----------> |                      |
|                             |        |  bindings: [         |
+-----------------------------+        |    fun = <Function>  |
                                       |  ]                   |
                                       |  [[outerEnv]] --+    |
                                       |                 |    |
                                       +-----------------|----+
                                                         |
                                                         v
                                                        null
FZs
  • 16,581
  • 13
  • 41
  • 50
  • Thank you for your answer, but I'm confused with the [FunctionDeclarationInstantiation](https://tc39.es/ecma262/#sec-functiondeclarationinstantiation)'s 20. It seems that if the function is no-strict, a new `Environment Record` whose `[[outerEnv]]` is the current `LE` will be created. And then set `LE` to the new `Environment Record`. – 用户17435438 Dec 10 '21 at 02:56