浅析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 相关文章推荐
lib.utf.js
Aug 21 Javascript
基于js disabled="false"不起作用的解决办法
Jun 26 Javascript
js通过八个点 拖动改变div大小的实现方法
Mar 05 Javascript
js获取当前页面的url网址信息
Jun 12 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
Nov 13 Javascript
使用jQuery简单实现模拟浏览器搜索功能
Dec 21 Javascript
jquery右下角自动弹出可关闭的广告层
May 08 Javascript
JavaScript学习笔记之取数组中最大值和最小值
Mar 23 Javascript
原生js实现倒计时功能(多种格式调用)
Jan 12 Javascript
javascript+html5+css3自定义弹出窗口效果
Oct 26 Javascript
轻松理解vue的双向数据绑定问题
Oct 30 Javascript
vue cli 全面解析
Feb 28 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 curl实现抓取302跳转后页面的示例
2014/07/04 PHP
JavaScript 嵌套函数指向this对象错误的解决方法
2010/03/15 Javascript
JQuery Dialog的内存泄露问题解决方法
2010/06/18 Javascript
打豆豆小游戏 用javascript编写的[打豆豆]小游戏
2013/01/08 Javascript
flash调用js中的方法,让js传递变量给flash的办法及思路
2013/08/07 Javascript
jquery判断元素是否隐藏的多种方法
2014/05/06 Javascript
JavaScript中Math.SQRT2属性的使用详解
2015/06/14 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
2015/10/27 Javascript
jquery实现触发时更新下拉列表内容的方法
2015/12/02 Javascript
微信小程序 input输入框控件详解及实例(多种示例)
2016/12/14 Javascript
基于JavaScript实现新增内容滚动播放效果附完整代码
2017/08/24 Javascript
[原创]js实现保存文本框内容为本地文件兼容IE,chrome,火狐浏览器
2018/02/14 Javascript
vue全屏事件开发详解
2020/06/17 Javascript
使用Vant完成Dialog弹框案例
2020/11/11 Javascript
[46:02]DOTA2上海特级锦标赛D组资格赛#2 Liquid VS VP第二局
2016/02/28 DOTA
Python导入txt数据到mysql的方法
2015/04/08 Python
用Python PIL实现几个简单的图片特效
2019/01/18 Python
基于树莓派的语音对话机器人
2019/06/17 Python
python+django+rest框架配置创建方法
2019/08/31 Python
用Python解数独的方法示例
2019/10/24 Python
Tensorflow获取张量Tensor的具体维数实例
2020/01/19 Python
利用Python实现斐波那契数列的方法实例
2020/07/26 Python
用HTML5实现鼠标滚轮事件放大缩小图片的功能
2015/06/25 HTML / CSS
英国在线滑雪板和冲浪商店:The Board Basement
2020/01/11 全球购物
工厂厂长的职责
2013/12/12 职场文书
优秀的自荐信要注意哪些
2014/01/03 职场文书
银行营业厅大堂经理岗位职责
2014/01/06 职场文书
法制宣传标语集锦
2014/06/25 职场文书
2014迎国庆演讲稿
2014/09/19 职场文书
2015元旦节寄语
2014/12/08 职场文书
运动会闭幕词
2015/01/28 职场文书
雷峰塔导游词
2015/02/09 职场文书
2015年房产经纪人工作总结
2015/05/15 职场文书
好人好事新闻稿
2015/07/17 职场文书
使用numpy nonzero 找出非0元素
2021/05/14 Python
详解在OpenCV中如何使用图像像素
2022/03/03 Python