调用上下文评估形式参数初始化器时的 `eval` 声明实例化

问题描述

PerformEval 抽象操作下面的注释说:

eval 代码不能实例化变量或函数绑定 调用 eval if 的调用上下文的变量环境 调用上下文正在评估形式参数初始值设定项 或者如果 调用上下文的代码或 eval 代码是严格模式 代码。相反,这样的绑定在一个新的 仅可由 eval 代码访问的 VariableEnvironment。绑定 由 let、const 或 class 声明引入的总是 在新的 LexicalEnvironment 中实例化。

问题:

“如果调用上下文正在评估形式参数初始值设定项”是什么意思?什么是“参数初始值设定项”?

Note 3 of 9.2.10 中的规范中只有一个其他引用术语“参数初始值设定项”。这篇笔记说:

参数初始化器可能包含直接的 eval 表达式。任何上衣 此类 eval 的级别声明仅对 eval 代码可见 (10.2)。为此类声明创建环境是 14.1.22 中描述。

我将此解释为,如果参数初始值设定项表达式包含 eval 调用,则在该 eval 调用中创建的任何变量都不会在参数范围内实例化。因此,在下面的示例中,我期望抛出 ReferenceError,因为不应在参数范围内实例化 c

function t(a = eval('var c = 8'),b = () => c) {
  console.log(b())
}

t() // 8 

但是正如您从控制台输出中看到的那样,我的解释是不正确的。即使 c 是在 eval 调用中创建的,它的值仍然对 b 定义的 funarg 可见,因此可以打印到控制台。

解决方法

原来你发现了一个规范错误!我在 TC39 的 Matrix 聊天中询问,他们已经创建了一个 PR 来删除此注释:

https://github.com/tc39/ecma262/pull/2428

注释中的行为使用是正确的,但在 2017 年在 https://github.com/tc39/ecma262/pull/1046

中被删除