I read a lot of articles, I was very confused, I also read the ES6 official documentation.
When creating an execution context, LE and VE initially point to the same Lexical Environment. But then the document says let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment.
Since it's the same, Do they refer to lexical environments that have both let-defined and var-defined variables? Or do we create a new lexical environment when we encounter let/const, and then have LE point to this new lexical environment, as I have shown below?
here is the code
0: function do_something() {
1: var a = 1;
2: let b = 2;
3: while (true) {
4: var c = 3;
5: let d = 4;
6: console.log(b);
7: break;
8: }
9: }
10:
11: do_something();
When executing a function, create the execution context as follows,with LE and VE pointing to the same lexical environment
ExecutionContext:
LexicalEnvironment:
a -> undefined, c -> undefined
outer: global
VariableEnvironment:
a -> undefined, c -> undefined
outer: global
...
But there is let/const, so a new lexical environment is created and LE points to the newly created lexical environment.
ExecutionContext:
LexicalEnvironment:
b -> uninitialized
outer: VariableEnvironment //here should VariableEnvironment,也就是当前执行上下文的词法环境
VariableEnvironment:
a -> undefined, c -> undefined
outer: global
...
When you encounter while, you need to create a new block-level scope that is, a new lexical environment
ExecutionContext:
LexicalEnvironment:
d -> uninitialized
outer:
LexicalEnvironment
b -> 2
outer: VariableEnvironment
VariableEnvironment:
a -> 1, c -> undefined
outer: global
...
and When we leave the while block we restore the original lexical environment.
ExecutionContext:
LexicalEnvironment:
b -> nothing
outer: VariableEnvironment //here should VariableEnvironment,也就是当前执行上下文的词法环境
VariableEnvironment:
a -> undefined, c -> undefined
outer: global
...
Following this model, I feel that variable lookup can be done normally, but I don't know it's right or not. I read a lot of articles that separate LE and VE, but the documentation says that they start with the same value, which makes me very confused
I looked at the official ES6 documentation, as well as many other articles.
Ah, I found that this seems to be unable to explain the situation of encountering closures.
Yes. The rules for initialising the environment guarantee that there are no naming conflicts between lexical and var-scoped variables, i.e. it does not need to distinguish between them by putting them in different environments but it just throws an exception when encountering a
let(orconst,classetc) and avar(orfunction) declaration with the same name.No. The environments are created and initialised with the declared variables when the new scope is entered, typically when calling a function or entering a block.
So why is this VariableEnvironment component of the execution needed at all, you might wonder? Actually, its only use is an edge case: direct
evalcalls in sloppy mode. They can introducevariable andfunctiondeclarations in an existing environment record, namely the VariableEnvironment of the current execution context in which theeval()call was made.