LexicalEnvironment 的 [[outerEnv]] 是否引用 VariableEnvironment(具有相同的执行上下文)

Does LexicalEnvironment’s [[outerEnv]] refer to the VariableEnvironment(of same Execution Context)

在下面的函数中,LexicalEnvironment的[[outerEnv]]是否引用了VariableEnvironment(属于同一个Execution Context的VariableEnvironment)

或者LE,VE相同且[[outerEnv]]都引用全局EnvironmentRecord?

function fun(){
  let a = 1
  var b = 2
}

TL;DR: 在函数内部,[[VariableEnvironment]][[LexicalEnvironment]] 都指向同一个环境记录,而 [[outerEnv]] 指向在其中创建函数的环境记录。


Execution Context的[[VariableEnvironment]]内部属性指向对应的函数作用域,即var和函数声明创建Bindings的作用域

另一方面,[[LexicalEnvironment]] 指向当前块作用域。这是由 letconstclasscatchwith 语句创建的绑定所在的位置,也是绑定查找发生的位置。

为每个块生成一个新的 [[LexicalEnvironment]],而只有一个 [[VariableEnvironment]] 为执行上下文创建。

在函数的最顶层范围(它们有自己的执行上下文)上,这两个是相同的,实际上,它们指向相同的环境记录。您可以在 PrepareForOrdinaryCall 中看到这一点,它在调用函数之前进行评估:

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.

强调我的

那个Environment Record的[[outerEnv]] 属性指向函数的[[Environment]],也就是构造函数的Environment Record

作为内部方块 [[LexicalEnvironment]] 的环境记录的 [[outerEnv]],指向它所在方块的环境记录。

因此,在您的情况下,它看起来像这样:

+-----------------------------+
|    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