auto semicolon insertion 自动分号补齐的坑
今天发现js自动分号补齐的坑,来看如下两段代码:
function Hello(){
    return
    {
        name: ’JavaScript’
    };
}
alert(Hello());
//输出undefined
function Hello(){
    return{
        name: ’JavaScript’
    };
}
alert(Hello());
//输出 [object Object]
略看代码,差不多,但是输出却不一样。仔细看看第一段代码return后面多了个换行。我们平时写后端代码也经常有会这样换行后花括号左对齐的写法。但是在js这里这样写却有不同的输出。这种机制叫分号自动补齐机制( auto semicolon insertion,简称ASI )。
知乎上有大神关于这个机制的解释:
在ASI的机制中有一类语句叫做restricted productions(不知道中文叫啥)。简单来说,就是组成这类语句的两个token当中不允许出现换行符 \n。如果在第一个token后面遇到了换行符,则判断语句结束,插入分号。restricted productions包括:
- return xxx (xxx是要返回的对象)
 - throw xxx(xxx是要抛出的错误对象)
 - break / continue xxx(xxx是循环的标签)
 - 作为后缀的 ++ / --
 
其中前几个关键词还是挺容易记的,最后一条的原因是需要区分以下情况:
a
++
b
因为++/--既可以作为前缀又可以作为后缀,在这样的情况下作为后缀解析会遇上换行符,所以只能作为b的前缀,自动插入分号后变成:
a; ++b;
回到原题,Douglas Crockford认为 { 应该写在行尾,是为了避免换行符导致return直接返回undefined。
篇外:关于分号 ------------------------------------------------------------------------------------------------
很多人觉得ASI坑太多了所以提倡永远手动加分号,这样就不用费心去研究ASI的规则了。但事实上,即使永远手动加分号,你依然会被restricted productions这条规则坑,因为它是在你不想要分号的地方给你插入分号。所以不管你喜不喜欢分号,都最好花点时间好好了解一下ASI的规则。而一旦你知道了ASI所有的坑,不写分号其实是很简单的。
ASI真正需要注意的坑只有两个,restricted productions是其一,另一个就是当下一行开头是 ( [ / 这三个字符之一的时候:
a = b
(function () { ... }())
会被解析成
a = b(function () {...}());
换言之,( ) 会被看做是在调用函数b。同理,[ ] 会被看做是在获取b的属性,而被斜杠坑的情况则要求更苛刻一些:
a = b
/Error/i.test(str) && doSomething()
第二行的写法本身比较少见,但也不是不可能。结果会被解析成:
a = b / Error / i.test(str) && doSomething();
斜杠被解析成了除号!
要躲开这个坑,其实真的挺简单,只要尽量别用这三个字符作为一行开头就行了。事实上遇到比较多的也只有括号开头。真的避不开的话,可以在行头手动加个分号:
a = b
;(function () { ... }())
额外的一点是在for循环声明里面的分号是永远不能省的,ASI不会在for循环声明中插分号,但一般正常人不会把for的声明分三行写吧...
每次我看到 “javascript分号坑很多,所以应该永远加分号” 这样的说法总是有些不屑的,因为永远加分号并不是避免错误的办法,搞懂ASI是怎么回事才是。只要理解了这里说的两个坑,javascript里99%的分号都是不必要的。
auto semicolon insertion 自动分号补齐的坑的更多相关文章
- 【微收藏】来自Twitter的自动文字补齐jQuery插件 - Typeahead.js
		
没图没逼格 事发有因 该插件可以结合本地数据进行一些操作.推荐关注一下H5的几种数据存储的方式(localstorage与sessionstorage.IndexedDB.离线缓存manifest文件 ...
 - jQuery实现Twitter的自动文字补齐特效
		
上图效果可以使用jQuery插件Typeahead.js来实现,这款jQuery插件来自于Twitter的一个新的项目,支持远程和本地的数据集.比较有特色的地方在于你可以将数据集使用本地存储(loca ...
 - CocoaPods 导入第三方库头文件自动补齐
		
使用了一段时间CocoaPods来管理Objective-c的类库,方便了不少.但是有一个小问题,当我在xcode输入import关键字的时候,没有自动联想补齐代码的功能,需要手工敲全了文件名,难以适 ...
 - CocoaPods导入第三方库头文件自动补齐
		
使用了一段时间CocoaPods来管理Objective-c的类库,方便了不少.但是有一个小问题,当我在xcode输入import关键字的时候,没有自动联想补齐代码的功能,需要手工敲全了文件名,难以适 ...
 - GBin1插件推荐之马可波罗(Marco Polo),jQuery的自动补齐插件 - Autocomplete Plugin
		
让我们Google一下"jQuery autocomplete plugin"(jquery自动补齐插件).在过去的4年中,我已经Google了很多次这个组合了.然而结果并没有变化 ...
 - Eclipse  -- 自动补齐设置和其他用法
		
1:自动补齐设置:最简单的修改方式是:Windows——>Preferences——>Java-->Editor-->Content Asist,在Auto activatio ...
 - js获取系统时间时自动补齐日期带零
		
最近在开发中发现有日期不规范的问题,正常规则应该是yy-mm-dd,而在输出时候却变成yy-mm-d,这是js的date()方法在作怪 解决思路是若在10号前,则自动给它补齐一个0,下面给出解决方法, ...
 - 为Debian/Ubuntu的apt-get install添加自动补齐/完成功能
		
Debian/Ubuntu的apt-get太常用了,不过偶尔可能也会碰到不太熟悉,想不起来的包的名称,除了去debian packages去查找,另外的方法就是给Debian/Ubuntu添加自动补齐 ...
 - jquery.autocomplete自动补齐和自定义格式
		
1.简单的下拉自动补齐,可以使用本地或远程数据源 <input name="autoTag" id="autoTag" /> var source ...
 
随机推荐
- 设置多个ip ,实现ip欺骗
			
网关和DNS填写: 使用IP欺骗功能必须得本地有多个可用IP,通常普通的PC机只有一个物理网卡,这就需要我们手工设置多IP绑定同一网卡: a.开始菜单 -> 控制面板 -> ...
 - 学习笔记之Unit testing/Integration testing/dotnet test and xUnit
			
source code https://github.com/haotang923/dotnet/tree/master/src Unit testing C# code in .NET Core u ...
 - [转]SQL Server 中 Cast 与 Convert
			
两者都用于:将一种数据类型的表达式转换为另一种数据类型的表达式. 安装有 Sql Server 2008 时可以浏览:ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.zh-C ...
 - tp5模型笔记---多对多
			
关联模型 一对一:HAS_ONE 以及对应的BELONEGS_TO 一对多:HAS_MANY 以及相对的BELONGS_TO 多对多:BELONGS_TO_MANY 步骤: 第一:创建Users模型 ...
 - Javascript框架
			
网易开源框架http://www.oschina.net/p/nej http://www.linuxeden.com/html/develop/20120716/127404.html 16 款最流 ...
 - Ps操作技巧(快捷键大全)
			
一.工具箱(多种工具共用一个快捷键的可同时按[Shift]加此快捷键选取) 矩形.椭圆选框工具 [M] 移动工具 [V] 套索.多边形套索.磁性套索 [L] 魔棒工具 [W] 裁剪工具 [C] 切片工 ...
 - matlab下将图片序列转化为视频文件 &&  将为视频文件转化图片序列
			
将图片序列转化为视频文件 程序如下: framesPath = 'E:\img\';%图像序列所在路径,同时要保证图像大小相同 videoName = 'Bolt.avi';%表示将要创建的视频文件的 ...
 - ExtJS的数据模型
			
给大家介绍一下ExtJS的组件模型. 常见的Ajax的开发流程: 1.定义URL,metod,params 2.开发后台 接收JSON/XML数据 返回JSON/XML数据 3.前台回调 4.显示到 ...
 - 学习MongoDB 七: MongoDB索引(索引基本操作)(一)
			
一.简介 在MongoDB建立索引能提高查询效率,只需要扫描索引只存储的这个集合的一小部分,并只把这小部分加载到内存中,效率大大的提高,如果没有建立索引,在查询时,MongoDB必须执行全表扫描,在数 ...
 - 函数图  https://www.processon.com/mindmap/5b5077fae4b040415ae39c64
			
---恢复内容结束---