javascript - 将 block 与对象初始值设定项区分开来

标签 javascript syntax grammar ecmascript-5

这与其说是一个实际问题,不如说是一个理论问题。它是关于解析一些由花括号分隔的代码。

这里有两个例子 object initializers :

f({});
({a:3})

这里有两个例子 blocks :

;{}
{a:3;}

在实践中,如果前面的代码需要一个表达式,{...} 似乎会分开一个 block 。

但我从未在 ECMAScript 规范中看到过明确或明显的规则,我什至不确定它是否属实。

某处是否有明确的非歧义引用?如果这条规则不是正确的规则?

最佳答案

Is there a definitive non ambiguous reference somewhere ?

它有点遍布整个规范。

简短的回答:

这取决于构造出现的上下文(这就是为什么它遍布规范)。它最具体的地址可能是 §12.4 ,它表示 ExpressionStatement(在需要语句的地方使用的表达式)不能以 { 开头。

长答案:

关键是解析器在遇到 { 时所期待的:如果它期待一个语句,那么它知道 { 开始一个 block 。但是如果它期待一个表达式,那么它就知道 { 开始一个对象初始值设定项。让我们看一个作业:

doThis();   // This line is just for context
x = {a: 3};

在上面第二行的开头,解析器期待一个语句。但是随后它看到了 x = 并且知道它正在处理一个赋值;那时,在看到 = 之后,解析器需要一个表达式声明在那里是无效的。所以它知道 { 启动了一个对象初始化器,而不是一个 block 。

对比:

doThis();   // This line is just for context
{a: 3};

上面的第二行是一个包含标记语句的 block 。 (看起来很奇怪;我们会回过头来讨论它。)解析器知道这一点,因为在该行的开头,解析器期待的是语句,而不是表达式。

解析器希望在许多其他地方看到表达式,而不是语句。例如,在属性初始值设定项中的 : 之后:

obj = {
    prop: {a: 3}
};

...或在执行函数调用时在参数内:

foo({a: 3});

...或在一元运算符之后,或刚好在开头 ( 等之后。在规范中,您可以通过解析器在语法中所说的内容来判断解析器将期待什么解析器正在解析,例如 §12.5 中定义 if 语句的语法图:

 IfStatement :

if ( Expression ) Statement else Statement
if ( Expression ) Statement

That tells us that when handling an if statement, within the () the parser expects an expression, but after the if () bit, it expects a statement.

So far so good, but JavaScript allows (almost) any expression wherever a statement is allowed. This is valid, for instance:

doThis();   // This line is just for context
flag && doThat();

上面的第二行是一个二元逻辑运算符表达式,但是是独立的。解析器在遇到语句时期待它。所以 && 表达式就是规范中所说的 ExpressionStatementExpressionStatement§12.4 定义.

所以这给我们留下了一些歧义:如果解析器期待一个语句,并且看到一个 {,它怎么知道这不是作为 的对象初始化表达式的开始表达式语句?

答案是:按法令执行。 :-) §12.4 在定义 ExpressionStatement 时这样说:

NOTE An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block.

所以没有歧义,不是因为一些微妙的语法技巧,而是因为规范是这样说的。 :-)

(如果您真的有理由想要将对象初始化表达式用作语句,您可以这样做;只需将它放在 () 中即可。)

关于javascript - 将 block 与对象初始值设定项区分开来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21522426/

相关文章:

parsing - 使用 Parsec 解析正则表达式

javascript - JavaScript 语法部分的左因式分解

javascript - 如何将对象作为方法参数传递到 javascript 中而不出现意外的标识符错误

python - 通过 pyAMF channel 发送的 kwargs

css - -ms-filter 和过滤器 CSS 规则允许的语法

objective-c - 从 Objective C 调用 swift 方法

javascript - 如何在 FireFox 中检查 Javascript 中的无效日期

javascript - 创建名为 ReadName() 的 Javascript 函数

javascript - 依赖脚本的 CDN 后备

c++ - Antlr4 C++访问歧义分支