JavaScript解释器会忽略语法错误

3
这段代码显然是有问题的:

if (5 > 2) {
  console.log("5 > 2");
} else (5 < 2) {
  console.log("5 < 2");
}

else不应该指定条件。执行此代码将导致SyntaxError:Unexpected token {,正如预期的那样。


问题在于,在进行轻微更改(将左括号转移到新行)后,解释器将简单地忽略语法错误。

这段代码:

if (5 > 2) {
  console.log("5 > 2");
} else (5 < 2)
{
  console.log("5 < 2");
}

以下是输出结果(在Chrome和Firefox中测试过):
5 > 2
5 < 2

这怎么可能呢?为什么这个else没有被视为语法错误?

看起来差不多正确。第二个代码块{ console.log("5 < 2"); }根本不被视为else的一部分......而( 5 < 2 )虽然毫无意义,但是它是有效的——就像是else { ( 5<2 ) } - Jaromanda X
3个回答

6

区别在于第二种情况中的回车使得第二个括号块成为一个独立的块,而不是 else 子句的一部分,其中括号部分是 else 子句。第二种情况等同于:

if (5 > 2) {
    console.log("5 > 2");
} else {
    (5 < 2)
}

{
    console.log("5 < 2");
}

就是这样:

if (5 > 2) {
    console.log("5 > 2");
} else {
    false
}

console.log("5 < 2");

3

这全部都是由于自动分号插入,当你把这个大括号移到下一行时,JS引擎会将你的代码"翻译"成这样:

if (5 > 2) {
  console.log("5 > 2");
} else (5 < 2);
{
  console.log("5 < 2");
}

显然是正确的,因为JS允许放置独立的块。

3
不同解释的原因在于第一条“ECMAScript自动分号插入规则”(ECMAScript Rules of Automatic Semicolon Insertion):ECMAScript Rules of Automatic Semicolon Insertion
当程序从左到右解析时,如果遇到任何一个语法规则不允许的符号(称为违规符号),且如下条件之一成立,则会在违规符号前自动插入分号:
  1. 违规符号与前面的符号之间至少有一个LineTerminator。
  2. 违规符号是}
在您的代码中,违规符号是{。在第一个版本的代码中,上述两个条件都不满足,因此不会插入分号并引发语法错误。
在您的代码的第二个例子中,存在行终止符,符合上述第一个条件。那么会自动插入分号,解析后的代码实际上变成了这个样子:
if (5 > 2) {
  console.log("5 > 2");
} else (5 < 2);
{
  console.log("5 < 2");
}

现在,代码是有效的,因为分号后面的左大括号被解释为不是跟随else表达式部分的代码块的开始。

请注意,即使这段代码现在可以解析,显然else部分的表达式没有任何效果。


非常感谢您给出如此快速和详尽的答案 :) 当我对代码进行自动美化后,输出结果居然不同,我简直震惊了。 - Maciej Wiercioch
不用谢。自动逗号插入确实是 JavaScript 中不太被赞赏的语法规则之一。 - trincot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接