区分块和对象初始值设定项

2024-05-22

这更多的是一个理论问题,而不是一个实际问题。这是关于解析一些由大括号分隔的代码。

这是两个例子对象初始值设定项 http://es5.github.io/#x11.1.5 :

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

这是两个例子blocks http://es5.github.io/#x12.1 :

;{}
{a:3;}

在实践中,似乎{...}如果前面的代码需要表达式,则将块分开。

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

某处是否有明确的、明确的参考?如果这条规则不是正确的,那么这是一条正确的规则吗?


某处是否有明确的、明确的参考?

它有点遍布整个规范。

简短的回答:

这取决于构造出现的上下文(这就是它遍布整个规范的原因)。它所解决的最具体的地方可能是§12.4 http://www.ecma-international.org/ecma-262/5.1/#sec-12.4,其中说表达式语句(在需要语句的地方使用的表达式)不能以{.

长答案:

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

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

在上面第二行的开头,解析器正在等待一个语句。但随后它看到x =并知道它正在处理任务;那时,在看到=,解析器期待一个表达. A 陈述在那里无效。所以它知道{启动对象初始值设定项,而不是块。

相比之下:

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

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

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

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

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

foo({a: 3});

...或在一元运算符之后,或在开口之后(在规范中,您可以通过解析器正在解析的语法中所说的内容来判断解析器期望什么,例如这个语法图来自§12.5 http://www.ecma-international.org/ecma-262/5.1/#sec-12.5定义if陈述:


 IfStatement :

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

这告诉我们,当处理一个if声明中,在()解析器需要一个表达式,但在if ()位,它需要一个声明。

到目前为止一切都很好,但是只要允许语句,JavaScript 就允许(几乎)任何表达式。这是有效的,例如:

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

上面的第二行是一个二元逻辑运算符表达式,但是独立的。解析器在遇到语句时正在等待它。所以&&表达式是规范中所说的表达式语句. 表达式语句定义为§12.4 http://www.ecma-international.org/ecma-262/5.1/#sec-12.4.

因此,这给我们留下了一些歧义:如果解析器期望一个语句,并且看到一个{,它如何知道这不是充当对象初始值设定项表达式的开头表达式语句?

答案是:按命令。 :-) §12.4 在定义时说了这一点表达式语句:

NOTE An 表达式语句不能以左大括号开头,因为这可能会使其与Block.

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

(如果您确实有理由想要使用对象初始值设定项表达式作为语句,您可以这样做;只需将其放在().)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

区分块和对象初始值设定项 的相关文章

随机推荐