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]]
指向当前块作用域。这是由 let
、const
、class
、catch
和 with
语句创建的绑定所在的位置,也是绑定查找发生的位置。
为每个块生成一个新的 [[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:
- Let callerContext be the running execution context.
- Let calleeContext be a new ECMAScript code execution context.
- Set the Function of calleeContext to F.
- Let calleeRealm be F.[[Realm]].
- Set the Realm of calleeContext to calleeRealm.
- Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
- Let localEnv be NewFunctionEnvironment(F, newTarget).
- Set the LexicalEnvironment of calleeContext to localEnv.
- Set the VariableEnvironment of calleeContext to localEnv.
- Set the PrivateEnvironment of calleeContext to F.[[PrivateEnvironment]].
- If callerContext is not already suspended, suspend callerContext.
- Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
- NOTE: Any exception objects produced after this point are associated with calleeRealm.
- 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
在下面的函数中,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]]
指向当前块作用域。这是由 let
、const
、class
、catch
和 with
语句创建的绑定所在的位置,也是绑定查找发生的位置。
为每个块生成一个新的 [[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:
- Let callerContext be the running execution context.
- Let calleeContext be a new ECMAScript code execution context.
- Set the Function of calleeContext to F.
- Let calleeRealm be F.[[Realm]].
- Set the Realm of calleeContext to calleeRealm.
- Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
- Let localEnv be NewFunctionEnvironment(F, newTarget).
- Set the LexicalEnvironment of calleeContext to localEnv.
- Set the VariableEnvironment of calleeContext to localEnv.
- Set the PrivateEnvironment of calleeContext to F.[[PrivateEnvironment]].
- If callerContext is not already suspended, suspend callerContext.
- Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
- NOTE: Any exception objects produced after this point are associated with calleeRealm.
- 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