不是特定于浏览器/实现的,但Section 7.9 Automatic Semicolon Insertion
ECMAScript语言规范值得一读。
7.9 自动分号插入
某些 ECMAScript 语句(空语句、变量语句、表达式语句、do-while 语句、continue 语句、break 语句、return 语句和 throw 语句)必须以分号结束。这样的分号可能总是显式地出现在源文本中。然而,为方便起见,在某些情况下,可以从源文本中省略此类分号。这些情况的描述是在这些情况下分号自动插入到源代码令牌流中。
7.9.1 自动分号插入规则 分号插入有三个基本规则:
当从左到右解析程序时,遇到任何语法生成都不允许的标记(称为违规标记)时,如果出现以下一项或多项,则在违规标记之前自动插入分号条件为真:
- 违规标记与前一个标记至少由一个 LineTerminator 分隔。
- 有问题的令牌是 }。
当程序从左到右解析时,遇到输入令牌流的结尾,并且解析器无法将输入令牌流解析为单个完整的 ECMAScript 程序,则在末尾自动插入分号输入流。
当程序从左到右解析时,遇到某个语法产生式允许的记号,但产生式是受限制的产生式,并且该记号将是紧跟注释之后的终端或非终端的第一个记号?[这里没有LineTerminator]?在受限产生式中(因此这样的记号称为受限记号),并且受限记号与前一个记号由至少一个 LineTerminator 分隔,然后在受限记号之前自动插入分号。但是,上述规则还有一个额外的覆盖条件:如果分号随后将被解析为空语句,或者如果该分号将成为 for 语句标题中的两个分号之一,则永远不会自动插入分号(参见12.6.3)。注意 以下是语法中唯一受限制的产生式: PostfixExpression : LeftHandSideExpression [no LineTerminator here] ++ LeftHandSideExpression [no LineTerminator here] -- ContinueStatement : continue [no LineTerminator here] Identifier ; BreakStatement : break [no LineTerminator here] Identifier ; ReturnStatement : return [no LineTerminator here] Expression ; ThrowStatement : throw [no LineTerminator here] Expression ; 这些限制产生式的实际效果如下:当遇到一个 ++ 或 -- 标记时,解析器会将其视为后缀运算符,并且在前面的标记和 ++ 或 -- 标记之间至少出现了一个 LineTerminator , 然后在 ++ 或 -- 标记之前自动插入一个分号。当一个继续,中断,返回,或者遇到 throw 标记并且在下一个标记之前遇到 LineTerminator,在 continue、break、return 或 throw 标记之后会自动插入一个分号。对 ECMAScript 程序员的实际建议是:后缀 ++ 或 -- 运算符应与其操作数出现在同一行。return 或 throw 语句中的 Expression 应与 return 或 throw 标记在同一行开始。break 或 continue 语句中的标识符应与 break 或 continue 标记位于同一行。return 或 throw 语句中的 Expression 应与 return 或 throw 标记在同一行开始。break 或 continue 语句中的标识符应与 break 或 continue 标记位于同一行。return 或 throw 语句中的 Expression 应与 return 或 throw 标记在同一行开始。break 或 continue 语句中的标识符应与 break 或 continue 标记位于同一行。
7.9.2 自动分号插入示例
来源
{ 1 2 } 3
不是 ECMAScript 语法中的有效句子,即使使用自动分号插入规则也是如此。相比之下,源
{ 1
2 } 3
也不是有效的 ECMAScript 语句,而是通过自动插入分号转换为以下语句:
{ 1
;2 ;} 3;
这是一个有效的 ECMAScript 语句。来源
for (a; b
)
不是有效的 ECMAScript 语句,并且不会被自动分号插入更改,因为 for 语句的标题需要分号。自动分号插入永远不会在 for 语句的标题中插入两个分号之一。来源
return
a + b
通过自动分号插入转换为以下内容:
return;
a + b;
注意 表达式 a + b 不被视为要由 return 语句返回的值,因为 LineTerminator 将它与令牌返回分开。来源
a = b
++c
通过自动分号插入转换为以下内容:
a = b;
++c;
注意 标记 ++ 不被视为应用于变量 b 的后缀运算符,因为 LineTerminator 出现在 b 和 ++ 之间。来源
if (a > b)
else c = d
不是一个有效的 ECMAScript 语句,并且不会被 else 标记之前的自动分号插入改变,即使此时没有应用语法产生,因为自动插入的分号将被解析为空语句。来源
a = b + c
(d + e).print()
不会通过自动分号插入进行转换,因为从第二行开始的带括号的表达式可以解释为函数调用的参数列表:
a = b + c(d + e).print()
在赋值语句必须以左括号开头的情况下,程序员最好在前面的语句末尾提供一个明确的分号,而不是依赖于自动分号插入。