这更像是一个理论问题,而不是一个实际问题。它是关于解决由花括号分隔的一些代码。
以下是object initializers的两个例子:
f({});
({a:3})
以下是blocks的两个例子:
;{}
{a:3;}
实际上,如果先前的代码需要表达式,{...}
似乎会分开一个块。
但我从来没有在ECMAScript规范中看到这样的规则明确或明显,我甚至不确定它是否属实。
某处有明确的非模棱两可的参考吗?一个正确的规则,如果这个不是吗?
答案 0 :(得分:7)
某处是否存在明确的非模糊引用?
它遍布整个规范。
答案简短:
这取决于构造出现的上下文(这就是为什么它超出了规范)。可能它所解决的最具体的地方是§12.4,其中它表示 ExpressionStatement (在预期语句中使用的表达式)不能以{
开头。< / p>
答案很长:
关键是解析器遇到{
时所期望的:如果它期望一个语句,那么它知道{
开始一个块。但如果它期望一个表达式,那么它知道{
开始一个对象初始化器。让我们看一下作业:
doThis(); // This line is just for context
x = {a: 3};
在上面第二行的开头,解析器期待一个语句。但后来它看到x =
并且知道它正在处理任务;此时,在看到=
之后,解析器期待表达式。 语句在那里无效。所以它知道{
启动一个对象初始化器,而不是块。
相反:
doThis(); // This line is just for context
{a: 3};
上面的第二行是一个包含标签声明的块。 (一个非常奇怪的一个;我们将回到那个。)解析器知道,因为在该行的开头,解析器期望一个语句,而不是一个表达式。
还有很多其他地方解析器希望看到表达式,而不是语句。例如,在属性初始值设定项中的:
之后:
obj = {
prop: {a: 3}
};
...或在进行函数调用时在参数内:
foo({a: 3});
...或者在一元运算符之后,或者在开始(
之后,等等。在规范中,您可以通过语法中的解析器所说的内容来分析解析器所期望的内容。解析,例如这个语法图来自§12.5定义if
语句:
IfStatement :
if ( Expression ) Statement else Statement
if ( Expression ) Statement
这告诉我们在处理if
语句时,在()
解析器中需要一个表达式,但在if ()
位之后,它需要一个语句。
到目前为止一直很好,但JavaScript允许(几乎)任何表达式允许的语句。这是有效的,例如:
doThis(); // This line is just for context
flag && doThat();
上面的第二行是二元逻辑运算符表达式,但是是独立的。解析器在遇到它时期待一个语句。因此,&&
表达式是规范称为 ExpressionStatement 的表达式。 ExpressionStatement 由§12.4定义。
这让我们有些含糊不清:如果解析器期待一个语句,并且看到{
,那么它是如何知道这不是作为 ExpressionStatement ExpressionStatement ExpressionStatement < EM>
答案是:通过命令。 :-)§12.4在定义 ExpressionStatement :
时说明了这一点注意 ExpressionStatement 不能以大括号开头,因为这可能会使 Block 模糊不清。
所以没有歧义,不是因为一些微妙的语法技巧,而是因为规范这么说。 : - )
(如果你有理由真的,真的想要将对象初始化表达式用作语句,你可以这样做;只需将它放在()
中。)