前言
相信从事过C#和Java的大家都知道分号是用作断句(EOS,end of statement)的,而且必须加分号,否则编译就不通过了。但JavaScript由于存在ASI机制,因此允许我们省略分号。ASI机制不是说在解析过程中解析器自动把分号添加到代码中,而是说解析器除了分号还会以换行为基础按一定的规则作为断句的依据,从而保证解析的正确性。
规范理论
es5 标准定义了自动分号插入规则,包括以下三个基本规则加两个前置条件:
前置条件
1、如果插入分号后解析结果是空语句,那么不会自动插入分号。
例子:(空语句,else
前不加分好)
if (a > b) else c = d
2、如果插入分号后它成为 for
语句头部的两个分号之一,那么不会自动插入分号。
例子:(不会加分号)
for (a; b )
基本规则
左到右解析程序,当遇到一个不符合任何文法产生式的 token
(叫做 违规 token(offending token)),那么只要满足下面条件之一就在违规 token
前面自动插入分号。
1、至少一个 LineTerminator 分割了违规 token
和前一个 token
。
2、违规 token
是 }。
例子:(1、2不符合任何产生式,并且之间存在 LineTerminator,因此在违规 token 2前加了分好,2和}则是因为违规 token
是 }所以加了分号)
{ 12 } 3
{ 1;2 ;} 3;
左到右解析程序,tokens
输入流已经结束,当解析器无法将输入 token
流解析成单个完整 ECMAScript 程序 ,那么就在输入流的结束位置自动插入分号。
对于受限产生式,也就是下面的5个,我们把产生式 [no LineTerminator here]后面的 token
叫做受限 token
,如果在 token
和 受限 token
间存在了至少一个 LineTerminator,那么会在受限 token
前自动加上 token
。
受限的产生式只限如下5个:
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;
归纳
避免 ASI 带来的问题
新闻热点
疑难解答
图片精选