ECMAScript 2017 中的 CallExpression 与 NewExpression

CallExpression vs NewExpression in ECMAScript 2017

根据 CallExpression 总是包含一个调用,因此不能成为 new 运算符后面的表达式的一部分。

然而,ECMAScript 2017 指出:

MemberExpression:
   PrimaryExpression
   MemberExpression [Expression]
   MemberExpression .IdentifierName
   MemberExpression TemplateLiteral
   SuperProperty
   MetaProperty
   new MemberExpression Arguments

并且:

NewExpression:
   MemberExpression
   new NewExpression

并且:

CallExpression:
   CoverCallExpressionAndAsyncArrowHead
   SuperCall
   CallExpression Arguments
   CallExpression [Expression]
   CallExpression .IdentifierName
   CallExpression TemplateLiteral

并且:

CoverCallExpressionAndAsyncArrowHead:
   MemberExpression Arguments

问题

  1. 为什么 MemberExpression Arguments 作品位于 14.7 Async Arrow Function Definitions 部分? Cover 是否意味着该规则涵盖 CallExpressionAsyncArrowHead,他们只是决定将其放在 14.7 而不是 12.3
  2. 根据上述产品,以下内容有效,因此与上面链接的 SO post 不符。我错过了什么吗?为什么要分NewExpressionCallExpression,如果NewExpression可以包含CallExpression

显然有效:

new new memberExpression(args);

new new MemberExpression Arguments,与第一个 CallExpression 产品相同。

Why is the MemberExpression Arguments production located in section 14.7 Async Arrow Function Definitions? Does Cover mean that the rule covers both CallExpression and AsyncArrowHead, and they just decided to put it in 14.7 instead of 12.3?

这是因为 async 不是关键字。这意味着在解析器中

async ()

只是对名为 async 的函数的函数调用。这意味着在

这样的片段的上下文中
async () =>

在找到 => 之前,解析器无法知道它实际解析的语法类型。这个概念是一组已知的标记,具有多种可能的输出 AST 结构,在规范中通过所谓的覆盖语法处理。

在规范的一般情况下,这本质上意味着 CoverCallExpressionAndAsyncArrowHead 本质上定义了您可以在箭头函数头或函数调用中找到的可能结构的并集。当解析器看到 => 时,它会说“好的,我解析的 CoverCallExpressionAndAsyncArrowHead 是箭头函数的头部,如果它发现 => 以外的任何东西,那么它就知道它实际上是一个函数调用。

According to the above productions, the below would be valid, thus breaking with the SO post linked above. Am I missing something? Why divide it in NewExpression and CallExpression, if NewExpression can contain CallExpression?

我还发现其他答案中的措辞有点难以理解,但我确实认为它是准确的。简短的回答是 then 被分成 NewExpressionCallExpression 因为 CallExpression 需要 括号,而 NewExpression 需要 not 是括号。例如,一般意义上的 new 是构造右侧任何内容的关键字。如果你做new Foo,它会构造Foo。如果你这样做 new obj.Foo 它将读取 obj.Foo 然后从中构造一个对象。这意味着在语法上你几乎可以认为这些是等价的:

// 1
var _tmp = Foo;
new _tmp;

// 2
var _tmp = obj.Foo;
new _tmp;

但这不是真的,因为它们是不同的:

// 3
var _tmp = Foo();
new _tmp;

// 4
new Foo();

new 关键字有 可选的 括号,正是这种行为需要在语法中进行划分。如果我们看看

NewExpression:
  MemberExpression
  new NewExpression

它总是直接跳转到 MemberExpression,这意味着 new obj() 会将 () 视为 new MemberExpression Arguments 中的 Arguments。由于 CallExpression 始终处理函数调用的 (),因此 NewExpression 语法仅适用于构造可选的 (),而

CallExpression:
  CoverCallExpressionAndAsyncArrowHead
  SuperCall
  CallExpression Arguments
  CallExpression [Expression]
  CallExpression .IdentifierName
  CallExpression TemplateLiteral

处理所有 () 涉及 没有 new.

的函数调用的情况