某处是否有明确的、明确的参考?
它有点遍布整个规范。
简短的回答:
这取决于构造出现的上下文(这就是它遍布整个规范的原因)。它所解决的最具体的地方可能是§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.
所以不存在歧义,不是因为一些微妙的语法技巧,而是因为规范是这么说的。 :-)
(如果您确实有理由想要使用对象初始值设定项表达式作为语句,您可以这样做;只需将其放在()
.)