gpt4 book ai didi

javascript - ECMAScript : Where can we find specification about accessibility of let/const variables

转载 作者:行者123 更新时间:2023-11-28 14:31:07 26 4
gpt4 key购买 nike

ECMAScript specification内,我们在哪里可以找到关于为什么 letconst 无法在使用 BlockStatements 创建的词法环境之外访问的明确规范>(与使用 var 声明的变量相反)?

如果BlockStatements现在创建new lexical environments ,那么 letconst 声明不应创建在该词法环境之外可访问的变量,但 var 变量应该创建。我试图了解最新的 ECMAScript 规范中具体指定了该行为的位置。

来自 13.3.1 Let and Const Declarations :

let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated.

来自 13.3.2 Variable Statement :

A var statement declares variables that are scoped to the running execution context's VariableEnvironment. Var variables are created when their containing Lexical Environment is instantiated and are initialized to undefined when created.

正如所见,两个变量声明在实例化它们所包含的词法环境时都会创建变量。对于 BlockStatement 来说,就是编译器进入 block 的时间。

来自 8.3 Execution Contexts :

LexicalEnvironment and VariableEnvironment components of an execution context are always Lexical Environments

最佳答案

正如您在 var 的描述中看到的,它的作用域为正在运行的执行上下文的 VariableEnvironment。有一个顶级 VariableEnvironment,然后创建一个新的 when you enter a function然后在 this part about Execution Contexts ,它是这样说的:

The LexicalEnvironment and VariableEnvironment components of an execution context are always Lexical Environments. When an execution context is created its LexicalEnvironment and VariableEnvironment components initially have the same value.

因此,在函数开始时,词法环境和变量环境是相同的。

然后,进入13.2.13 Runtime Semantics: Evaluation Block: { } ,您可以看到,当您进入该 block 时,会创建一个新的 LexicalEnvironment ,而当您离开该 block 时,会恢复之前的环境。但是,当您进入或离开 block 时,没有提及新的 VariableEnvironment(因为它在函数内保持不变)。

因此,由于 letconst 的作用域是声明它们的 LexicalEnvironment,并且是 block 本地的,因此无法在 block 外部访问它们。

但是,var 的作用域为 VariableEnvironment,它仅被创建并限定为整个函数,而不是一个 block 。

letconst 变量无法在其 LexicalEnvironment 之外访问,因为一旦执行上下文离开其 block (一旦当您离开该 block 时,它们的 LexicalEnvironment 本质上会从堆栈中弹出,并且不再位于解释器查找变量的作用域搜索链中。

<小时/>

当规范添加此内容时:

The [let and const] variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated.

这意味着即使在它们自己的词法环境中,您也无法访问它们,直到评估它们的定义为止。通俗地说,这意味着它们不会像 var 那样被提升到其作用域的顶部,因此在定义之后才能使用。这是通过在 LexicalEnvironment 中不初始化 letconst 变量来实现的,直到它的语句运行并且 GetBindingValue()查找变量的操作会发现它尚未初始化,并会抛出ReferenceErrorvar 变量立即初始化为 undefined,因此它们不会导致此 ReferenceError

您可以在这段代码中看到它是如何工作的:

let x = 3;

function test() {
x = 1;
let x = 2;
console.log("hello");
}
test();

let x = 3 行,变量 x 在外部 LexicalEnvironment 中初始化。

然后,当您调用 test() 时,在该函数的开头,会创建一个新的 LexicalEnvironment,该 block 中 x 的新声明将被放入新的 LexicalEnvironment,但尚未初始化。

然后,您将看到 x = 1 语句。解释器查找x,在当前LexicalEnvironment中找到它,但它尚未初始化,因此抛出ReferenceError

<小时/>

根据您评论中的问题:

I've been turning the spec upside down, but have a hard time spotting that VariableEnvironments are only created for functions. Could you perhaps add an answer showing what steps in the spec you follow to reach said conclusion?

您只需浏览规范中创建 VariableEnvironment 的所有位置,您就会发现这种情况发生的唯一位置是函数执行的开始处和顶层。

例如,以下是这些地方的一个:PrepareForOrdinaryCall 。还有其他一些。

但是,没有任何地方描述过在 block 开始时发生的这种情况,而只是在函数开始时描述。

这些规范的编写方式,它们描述了事情发生的时间,而不是没有发生的时间(这具有一定的逻辑意义),但这意味着要证明某事没有发生,你必须在任何地方都找不到这说明它确实发生了。

关于javascript - ECMAScript : Where can we find specification about accessibility of let/const variables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51543843/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com