JavaScript的自动分号插入算法的一部分是所谓的限制性制作"。这些是句法形式,禁止在某一点发生换行符。引用ECMAScript 2015规范:
如果在句法语法的制作右侧出现短语“[no LineTerminator here]”,则表示制作是限制制作:如果在指定位置的输入流中出现 LineTerminator ,则可能无法使用它。
ECMAScript 2015规范中有10个限制性作品:
++
--
continue
[no LineTerminator 此处] LabelIdentifier [?yield] ;
break
[no LineTerminator 此处] LabelIdentifier [?yield] ;
return
[no LineTerminator 此处] 表达式 ;
return
[no LineTerminator 此处] 表达式 [In,?Yield] ;
throw
[no LineTerminator 此处] 表达式 [In,?Yield] ;
=>
ConciseBody [?In] yield
[no LineTerminator 此处] {{1} } AssignmentExpression [?In,Yield] *
[no LineTerminator 此处] AssignmentExpression [?In,Yield] 在这些作品中,我理解选择使其中大部分都受到限制。限制 PostfixExpression 的生产以防止使用 PrefixExpression 解析歧义。 ContinueStatement , BreakStatement 和 ReturnStatement 限制了制作,因为yield
和break
没有采取相应的制作标签和continue
没有表达。我不能说我对箭头函数或者表达式已经足够了解它们为什么受到限制,但我认为它是为了防止某种类似的解析模糊。
我不理解的制作是 ThrowExpression 。据我所知,使用return
时没有解析歧义,就像使用throw
,break
和return
时一样:{{1是无效的JavaScript。我认为这可能是出于历史原因,但据我所知,continue
从未在任何JavaScript规范中被允许。
这样做的实际结果与throw;
非常相似,你不能把表达式抛到下一行,例如这是错误的:
throw;
但是,与return
不同,这与将throw
new Error("some error");
放在同一行上的行为并不相同。它只是一个语法错误:Chrome将其报告为
未捕获的SyntaxError:抛出后非法换行
ThrowExpression 的制作是否仅限于保持与类似结构的一致性?或者是否有一些我没有看到的歧义?
答案 0 :(得分:4)
在1998年左右将throw
添加到语言中时,讨论了throw语句是否需要表达式。 (替代方案是没有表达式的throw
重新抛出当前异常对象,如certain other languages中所示。)
我无法找到任何关于此讨论或最终解决方案的记录 - 虽然我们知道决议是什么 - 但在TC39 meeting notes中提到了2月19日的会议, 1998年。我认为限制的目的是让句法空间保持开放,以防有一天决定改变。
答案 1 :(得分:3)
我们只能在这里猜测为什么语言作者决定这样做,但我会说这是为了与return
保持一致。如果您想完成return ¶ value
,则禁止throw ¶ value
和value
。无论如何throw
都没有歧义并不重要。
答案 2 :(得分:2)
我认为adeneo's comment在正确的轨道上:与return
一样,throw
的操作数通常是一个有效的表达式。 return \n "valid on its own";
的问题是ASI问题最常见的例子之一,因此限制return
以及任何其他采用类似值的语句都是合理的保障。
查看列表,其中大多数是一元运算符(或看起来像一个)。它们都遵循相同的一般形式,箭头函数除外。该表单是导致ASI错误的原因,因此限制整个类别比return
更容易预测。