关于LexicalEnvironment与VariableEnvironment的理解是否正确?
LexicalEnvironment与VariableEnvironment的核心区别及执行流程解析
先明确ECMAScript规范的核心规则:
- 执行上下文创建时,LexicalEnvironment(LE)和VariableEnvironment(VE)初始指向同一个词法环境。这个初始环境会完成
var声明的变量提升(值为undefined)和函数声明的提升。 - VE从始至终固定指向这个初始环境,仅用于存储
var和函数声明的绑定。 - LE则是动态变化的:每当进入一个块级作用域(函数体、
if/while块、let/const所在的块等),都会创建一个新的词法环境,将其outer指向当前的LE,然后把LE更新为这个新环境。新环境专门存储当前块内的let/const声明(处于未初始化状态,形成暂时性死区);离开块级作用域时,LE会回退到之前的环境。
针对你提供的代码,正确的执行流程应该是这样:
代码示例:
function do_something() { var a = 1; let b = 2; while (true) { var c = 3; let d = 4; console.log(b); break; } } do_something();
1. 执行do_something(),创建函数执行上下文
此时LE和VE指向同一个初始词法环境,完成var声明的提升:
ExecutionContext: LexicalEnvironment: a -> undefined, c -> undefined outer: global VariableEnvironment: a -> undefined, c -> undefined outer: global ...
2. 进入函数体块级作用域
创建新的词法环境,将LE更新为这个新环境(其outer指向VE),并在其中添加let b的绑定(未初始化):
ExecutionContext: LexicalEnvironment: b -> uninitialized outer: VariableEnvironment // 指向初始环境 VariableEnvironment: a -> undefined, c -> undefined outer: global ...
执行var a = 1:VE中的a被赋值为1;执行let b = 2:LE中的b被赋值为2。
3. 进入while块级作用域
创建新的词法环境,LE更新为这个新环境(其outer指向当前的函数体LE),添加let d的绑定(未初始化):
ExecutionContext: LexicalEnvironment: d -> uninitialized outer: LexicalEnvironment(函数体) b -> 2 outer: VariableEnvironment VariableEnvironment: a -> 1, c -> undefined outer: global ...
执行var c = 3:VE中的c被赋值为3;执行let d = 4:当前LE中的d被赋值为4;console.log(b)时,从当前LE向上查找,找到函数体LE中的b,输出2。
4. 离开while块
LE回退到函数体的词法环境:
ExecutionContext: LexicalEnvironment: b -> 2 outer: VariableEnvironment VariableEnvironment: a -> 1, c -> 3 outer: global ...
关于你的模型的修正点
- 离开
while块后,b不会变成nothing,它依然存在于函数体的LE中,值为2,直到函数执行完毕。 - 不是“遇到
let/const时创建新LE”,而是进入块级作用域时创建新LE,let/const只是在当前块的LE中添加绑定。
闭包场景的解释
闭包的核心是函数的[[Environment]]属性会保留其创建时所在的LE引用。比如修改代码:
function do_something() { let b = 2; return function() { console.log(b); } } const fn = do_something(); fn(); // 输出2
当do_something执行时,返回的内部函数的[[Environment]]指向函数体的LE(包含b -> 2,outer指向VE)。即使do_something执行完毕,这个LE不会被垃圾回收,因为内部函数还在引用它。当调用fn()时,会创建新的执行上下文,其LE的outer指向这个保留的环境,从而能找到b的值,形成闭包。
内容的提问来源于stack exchange,提问作者1_sy
相关产品推荐
相关产品推荐

