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


Posted in Javascript onSeptember 29, 2016

前言

相信从事过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 还存在不换行的情况,这就要根据标准里的三条规则行事了!

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

小补充

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

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

总结

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

Javascript 相关文章推荐
js window.onload 加载多个函数和追加函数详解
Jan 08 Javascript
jQuery+CSS实现一个侧滑导航菜单代码
May 09 Javascript
Javascript使用SWFUpload进行多文件上传
Nov 16 Javascript
半个小时学json(json传递示例)
Dec 25 Javascript
JavaScript判断浏览器及其版本信息
Jan 20 Javascript
React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)
Jul 11 Javascript
jQuery 开发之EasyUI 添加数据的实例
Sep 26 jQuery
原生JS上传大文件显示进度条 php上传文件代码
Mar 27 Javascript
js装饰设计模式学习心得
Feb 17 Javascript
Vue中的v-for循环key属性注意事项小结
Aug 12 Javascript
如何使用 JavaScript 操作浏览器历史记录 API
Nov 24 Javascript
JavaScript缓动动画函数的封装方法
Nov 25 Javascript
完美解决IE9浏览器出现的对象未定义问题
Sep 29 #Javascript
JSON 对象未定义错误的解决方法
Sep 29 #Javascript
Node.js检测端口(port)是否被占用的简单示例
Sep 29 #Javascript
json定义及jquery操作json的方法
Sep 29 #Javascript
JavaScript中apply方法的应用技巧小结
Sep 29 #Javascript
老生常谈javascript变量的命名规范和注释
Sep 29 #Javascript
浅谈javascript:两种注释,声明变量,定义函数
Sep 29 #Javascript
You might like
PHP+JS无限级可伸缩菜单详解(简单易懂)
2007/01/02 PHP
探讨:parse url解析URL,返回其组成部分
2013/06/14 PHP
PHP的switch判断语句的“高级”用法详解
2014/10/01 PHP
php字符串函数学习之substr()
2015/03/27 PHP
基于PHP代码实现中奖概率算法可用于刮刮卡、大转盘等抽奖算法
2015/12/20 PHP
定义select的边框颜色
2008/04/28 Javascript
基于jquery实现漂亮的动态信息提示效果
2011/08/02 Javascript
Web跨浏览器进程通信(Web跨域)
2013/04/17 Javascript
jQuery学习笔记之jQuery+CSS3的浏览器兼容性
2015/01/19 Javascript
Javascript核心读书有感之表达式和运算符
2015/02/11 Javascript
深入理解jQuery中的事件冒泡
2016/05/24 Javascript
使用纯JS代码判断字符串中有多少汉字的实现方法(超简单实用)
2016/11/12 Javascript
微信小程序实现滑动切换自定义页码的方法分析
2018/12/29 Javascript
json解析大全 双引号、键值对不在一起的情况
2019/12/06 Javascript
js实现右键弹出自定义菜单
2020/09/08 Javascript
[01:07:20]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第二场 2月2日
2021/03/11 DOTA
把大数据数字口语化(python与js)两种实现
2013/02/21 Python
python根据出生日期返回年龄的方法
2015/03/26 Python
Python的time模块中的常用方法整理
2015/06/18 Python
python实现的AES双向对称加密解密与用法分析
2017/05/02 Python
HEMA英国:荷兰原创设计
2018/08/28 全球购物
如果一个类实现了多个接口但是这些接口有相同的方法名将会怎样
2013/06/16 面试题
自我反省检讨书
2014/01/23 职场文书
实用的简历自我评价
2014/03/06 职场文书
宣传部部长竞选演讲稿
2014/04/26 职场文书
收款委托书
2014/10/14 职场文书
个人诉讼委托书范本
2014/10/17 职场文书
护士个人年终总结
2015/02/13 职场文书
2015年社区纪检工作总结
2015/04/21 职场文书
2015年新教师工作总结
2015/04/28 职场文书
离婚案件被告代理词
2015/05/23 职场文书
七一表彰大会简报
2015/07/20 职场文书
2015年小学师德师风建设工作总结
2015/10/23 职场文书
2016幼儿园教师年度考核评语
2015/12/01 职场文书
HTML5中 rem适配方案与 viewport 适配问题详解
2021/04/27 HTML / CSS
《金肉人》米特&《航海王》阿鹤声优松岛实因胰脏癌去世 享寿81岁
2022/04/13 日漫