好吧,首先我应该问一下这是否依赖于浏览器。
我读到过,如果发现一个无效的令牌,但该代码段在该无效令牌之前是有效的,如果该令牌前面有换行符,则会在该令牌之前插入分号。
但是,对于分号插入导致的bug,引用的常见例子是:
return
_a+b;
。。它似乎不遵循这个规则,因为_a将是一个有效的标记。
另一方面,打破呼叫链如预期的那样起作用:
$('#myButton')
.click(function(){alert("Hello!")});
有人对规则有更深入的描述吗?
首先,您应该知道哪些语句受自动插入分号(为简洁起见,也称为ASI)的影响:
var
语句do-while
语句continue
语句break
语句返回
语句抛出
语句ASI的具体规则见规范§11.9.1自动分号插入规则
本文介绍了三种情况:
LineTerminator
与上一个令牌隔开。}
例如:
{ 1
2 } 3
转换为
{ 1
;2 ;} 3;
NumericLiteral
1
满足第一个条件,下面的标记是行终止符。2
满足第二个条件,下面的标记是}
。
例如:
a = b
++c
转换为:
a = b;
++c;
限制生产:
UpdateExpression :
LeftHandSideExpression [no LineTerminator here] ++
LeftHandSideExpression [no LineTerminator here] --
ContinueStatement :
continue ;
continue [no LineTerminator here] LabelIdentifier ;
BreakStatement :
break ;
break [no LineTerminator here] LabelIdentifier ;
ReturnStatement :
return ;
return [no LineTerminator here] Expression ;
ThrowStatement :
throw [no LineTerminator here] Expression ;
ArrowFunction :
ArrowParameters [no LineTerminator here] => ConciseBody
YieldExpression :
yield [no LineTerminator here] * AssignmentExpression
yield [no LineTerminator here] AssignmentExpression
典型的例子是ReturnStatement
:
return
"something";
转换为
return;
"something";
我不能很好地理解规范中的这3条规则--希望有一些更简单的英语--但下面是我从JavaScript:最终指南,第6版,David Flanagan,O'Reilly,2011年收集到的内容:
报价:
JavaScript并不把每个换行符都当作分号来处理:它通常只在无法解析没有分号的代码时才把换行符当作分号来处理。
另一个引语:对于代码
var a
a
=
3 console.log(a)
JavaScript不把第二个换行符当作分号,因为它可以继续解析较长的语句a=3;
和:
当JavaScript无法将第二行解析为第一行语句的延续时,它将换行符解释为分号这一一般规则的两个例外。第一个异常涉及return,break和continue语句
。。。如果在这些单词后面出现换行符。。。JavaScript总是将该换行符解释为分号。
。。。第二个异常涉及到++和−−运算符。。。如果要将这两个运算符中的任何一个用作后缀运算符,它们必须与它们应用的表达式出现在同一行。否则,换行符将被视为分号,++或--将被解析为应用于后面代码的前缀运算符。考虑以下代码,例如:
x
++
y
它被解析为x;++Y;
,不作为x++;Y
所以我想简化一下,这意味着:
通常,只要有意义,JavaScript就会将其视为代码的延续--除了两种情况:(1)在一些关键字(如return
,break
,continue
)之后,以及(2)如果在新行上看到++
或--
,那么它就会在前一行的末尾添加;
。
关于“只要有意义就把它当作代码的延续”的部分让人感觉像是正则表达式的贪婪匹配。
根据以上所述,这意味着对于返回
和换行符,JavaScript解释器将插入一个;
(再次引用:如果在这些单词[如return
]后出现换行符。。。JavaScript将始终将该换行符解释为分号)
由于这个原因,经典的例子
return
{
foo: 1
}
不会按预期工作,因为JavaScript解释器将其视为:
return; // returning nothing
{
foo: 1
}
return
:
return {
foo: 1
}
才能正常工作。如果要遵循在任何语句后使用;
的规则,您可以自己插入;
:
return {
foo: 1
};
直接来自ECMA-262第五版ECMAScript规范:
分号插入有三个基本规则:
LineTerminator
将有问题的令牌与前一个令牌分隔。但是,在前面的规则上还有一个附加的重写条件:如果分号随后被解析为空语句,或者该分号成为for语句标题中的两个分号之一,则从不自动插入分号(参见12.6.3)。