浅析Javascript的自动分号插入(ASI)机制

 更新时间:2016年09月29日 10:37:26   投稿:daisy  
我们大家都知道在写java和c时,必须要在语句后加分号,否则编译通不过。而js不同,存在自动分好插入机制,下文简称ASI。它会给源代码的 token 流自动插入分号。下面这篇文章我们就来谈谈Javascript的自动分号插入(ASI)机制。

前言

相信从事过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 是 }所以加了分号)

{ 1
2 } 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 带来的问题

     1、后缀运算符 ++ 或 -- 和它的操作数应该出现在同一行。

     2、return throw 语句的表达式开始位置应该和 return throw token 同一行。

     3、break 或 continue 语句的标示符应该和 break continue token 同一行。

何时加分号

无分号党(懒人党)想要不加分号,那么就需要知道什么时候应该要加分号。网上的一篇文章归纳了 NO ASI 并且会出现错误的几种情况,在这几种情况下我们是要加分号的。下面是对应的描述:

在以 ([/+- 开头的语句前加分号(由于正常写法均不会出现以 .,*% 作为语句开头,因此只需记住前面5个即可,你看能懒则懒哦)

不过这里只考虑了换行的情况,其实 ASI 还存在不换行的情况,这就要根据标准里的三条规则行事了!

知道了这点,其实我们就可以省略大部分的分号了。但是也不强求,因为这还是要根据个人习惯以及团队风格走的。

小补充

为什么自执行函数前要加分号?

主要是应对代码合并压缩时,由于缺少分号;带来的错误。知道了上面的规则,在 ( 开头的行前加分号就可以避免错误了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

相关文章

  • JS装饰者模式和TypeScript装饰器

    JS装饰者模式和TypeScript装饰器

    学习的目的是对装饰者模式模式有进一步的理解,并运用在自己的项目中;对TypeScript装饰器的理解,更好的使用装饰器,例如在nodejsweb框架中、vue-property-decorator中,或者是自定义装饰器,能熟练运用并掌握其基本的实现原理。
    2021-04-04
  • 微信公众号网页授权登录的超简单实现步骤

    微信公众号网页授权登录的超简单实现步骤

    微信开放平台为第三方移动程序提供分享、传播的接口,使用户可将第三方程序的内容发布给好友或分享至朋友圈,下面这篇文章主要给大家介绍了关于微信公众号网页授权登录的超简单实现方法,需要的朋友可以参考下
    2022-06-06
  • 详解组件库的webpack构建速度优化

    详解组件库的webpack构建速度优化

    这篇文章主要介绍了详解组件库的webpack构建速度优化,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • 用JavaScript编写COM组件的步骤

    用JavaScript编写COM组件的步骤

    用JavaScript编写出来的COM组件称为WSC。WSC即Windows脚本组件(Windows Scripting Component),是Microsoft COM的一个新技术,可以通过易于使用的脚本语言来创建。
    2009-03-03
  • JavaScript常用正则函数用法示例

    JavaScript常用正则函数用法示例

    这篇文章主要介绍了JavaScript常用正则函数用法,结合实例形式分析了JavaScript正则函数match、exec、test、search、replace、split的功能与具体使用技巧,需要的朋友可以参考下
    2017-01-01
  • cookie在javascript中的使用技巧以及隐私在服务器端的设置

    cookie在javascript中的使用技巧以及隐私在服务器端的设置

    cookie在javascript中的使用技巧,需要的朋友可以参考下
    2012-12-12
  • 无刷新预览所选择的图片示例代码

    无刷新预览所选择的图片示例代码

    这篇文章主要介绍了无刷新预览所选择的图片的具体实现,需要的朋友可以参考下
    2014-04-04
  • 基于js 各种排序方法和sort方法的区别(详解)

    基于js 各种排序方法和sort方法的区别(详解)

    下面小编就为大家分享一篇基于js 各种排序方法和sort方法的区别(详解),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • JS实现简易的图片拖拽排序实例代码

    JS实现简易的图片拖拽排序实例代码

    这篇文章主要介绍了JS实现简易的图片拖拽排序实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 轻松学习Javascript闭包

    轻松学习Javascript闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。这篇文章主要介绍了Javascript闭包,需要的朋友可以参考下
    2017-03-03

最新评论