JavaScript到底应不应该加分号?JavaScript自动插入分号规则详解
JavaScript 提供了 automatic semicolon insertion (ASI)自动插入分号规则,在不加分号的情况下,会自动补充分号来分隔不同语句。
导致在继左大括号换行、tab 和 space 圣战后,前端又出现了一场战争。
并且随着那个男人加入这场讨论之后,关于是否应该加分号的讨论更是激烈了。

ASI 自动插入分号规则
在决定是否添加分号之前,我们先来了解一下编译器到底在哪些情况下会自动插入分号,哪些情况必须手动添加分号。
会自动添加分号的情况
1.遇到换行符,但是两句代码连接是无效代码
// 代码
42
'hello'
// `42 'hello'`连接在一起是无效语句,所以会自动在之间插入分号
42;'hello'
// 直接明确的写法
42;"hello"
// 代码
let a = 10, b = 5
a
-
b
// a - b 为有效代码,所以三者之间不会自动加分号
a = 1; b = 2;
// 直接明确的写法
a - b
2.遇到换行符,但是两句代码之间不允许有换行符
// 代码
foo
++
bar
++
baz
// foo 和 ++ 符合规则1,但是不符合 no LineTerminator here规则,所以会添加分号
foo;
++bar;
++baz;
在 JS 标准中,有个 no LineTerminator here 的规则,规定哪些语法不能加入换行符,如果开发者加了换行符,则 JS 编译器会无法识别并加入分号。
- 带标签的
continue语句,不能continue后插入换行; - 带标签的
break语句,不能在break后面插入换行; return后面不能插入换行;- 后自增、后自减运算符前不能插入换行;
throw和Exception之间不能插入换行;async关键字,后面不能插入换行;- 箭头函数的箭头前,不能插入换行;
yield之后,不能插入换行。
3.Restricted productions
如果这些标签后,空一行书写其它语句,则会自动在这些标签后添加分号:
++or--returnbreakcontinue- ES6
yield、async等 - 反引号`
// return 后空一行再书写语句,则会自动在 return 后加分号
return
{
a: 1
}
// 这是正确写法
return {
a: 1
}
其它标签类似。
如果手动在这些标签后加上分号,同样也是错误的,比如:
// 空一行再写 a,会自动在 ++ 后添加分号
++
a
// 就算手动添加,和上面结果一样是错误的
++;
a;
所以针对 Restricted productions ,无论让编译器自动添加分号,还是自己手动加上分号,都是错误的,都应该去避免去换行,避免写这种写法。
必须手动加分号的情况
以下面这些标签开头的命令,必须在前面加分号,和前面一个语句分隔:
+和-:语句以 + 或者 - 开头/: 语句以正则表达式开头(: 语句以自执行函数开头[: 语句以数组开头
举例说明:
// 错误
a = b
+a
// 正确
a = b
;+a
// 错误
a = b
/something/.test(a)
// 正确
a = b
;/something/.test(a)
// 错误
a = b
(function () {})()
// 正确
a = b
;(function() {})()
// 错误
a = b
[1, 2, 3].forEach()
// 正确
a = b
;[1, 2, 3].forEach()
上面的情况,如果第二行代码不手动添加分号的话,两行代码会合并在一起导致结果错误或者报错。
上面几种情况中,只有自执行函数和数组开头会在极少情况下遇到,记住这两个前面要手动加上分号即可。
就算是习惯加分号的朋友,但仍然要注意下面的情况:
// 不需要结尾添加分号
if () {
}
// 不需要结尾添加分号
for () {
}
// 不需要结尾添加分号
while () {
}
// 需要在结尾添加分号
var a = function () {
};
// 需要在结尾添加分号
var a = {
prop: value
};
// 报错
[1, 2, 3].forEach();
即便习惯写分号的朋友,也很少有人在 if 、for、while 等语句 } 后写分号,但是如果使用赋值的形式传递,则一定要注意在 } 把分号添加上,以避免后面语句出现自执行和数组开头的语句。
推荐遇到自执行和数组开头的,直接前面加上分号就完事了。
总结
是否添加和是否手动加是两回事,我们可以用 eslint、Prettier 等工具自动生成或者删除分号,是否手动加可以看个人喜好,最终代码内可以根据项目要求用工具生成。
但都要注意必须添加分号的几种情况。
参考文章
- Hacking Semicolons
- What are the rules for JavaScript's automatic semicolon insertion (ASI)? - Stack Overflow
JavaScript到底应不应该加分号?JavaScript自动插入分号规则详解的更多相关文章
- 防止 JavaScript 自动插入分号
JavaScript语言有一个机制:在解析时,能够在一句话后面自动插入一个分号,用来修改语句末尾遗漏的分号分隔符. 然而,由于这个自动插入的分号与JavaScript语言的另一个机制发生了冲突,即所有 ...
- js 自动插入分号
先来看一个例子: function get(){ return { a:1 } } var r=get(); console.log(r); 似乎r的值应该是{a:1},然而运行结果却是undefin ...
- iOS开发——加载、滑动翻阅大量图片解决方案详解
加载.滑动翻阅大量图片解决方案详解 今天分享一下私人相册中,读取加载.滑动翻阅大量图片解决方案,我想强调的是,编程思想无关乎平台限制. 我要详细说一下,在缩略图界面点击任意小缩略图后,进入高清 ...
- SQL Prompt 格式化SQL会自动插入分号的问题
一.问题 安装新版SQL Prompt,格式化SQL都会自动在SQL末端插入分号 格式化前 格式化后 二.解决方法 选择SQL Prompt下的Options... 选择左侧的Format下Style ...
- Javascript面向对象三大特性(封装性、继承性、多态性)详解及创建对象的各种方法
Javascript基于对象的三大特征和C++,Java面向对象的三大特征一样,都是封装(encapsulation).继承(inheritance )和多态(polymorphism ).只不过实现 ...
- JavaScript 对象、DOM对象、jquery对象的区别、转换详解
一.JavaScript 对象 JavaScript 提供多个内建对象,比如 String.Date.Array 等等. 对象只是带有属性和方法的特殊数据类型. 访问对象的属性: [javascrip ...
- Android 平滑图片加载和缓存库 Glide 使用详解
在图片加载库烂大街的今天,选择一个适合自己使用的图片加载库已经成为了每一个Android开发者的必经之路.现在市面上知名的图片加载库有UIL,Picasso,Volley ImageLoader,Fr ...
- php中自动加载类_autoload()和spl_autoload_register()实例详解
一._autoload 自动加载类:当我们实例化一个未定义的类时,就会触此函数.到了php7.1以后版本不支持此函数好像抛弃了 新建一个类文件名字自己随便去:news类在auto.php文件里面去实例 ...
- Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解
前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式(Res ...
- [Aaronyang] 写给自己的WPF4.5 笔记6[三巴掌-大数据加载与WPF4.5 验证体系详解 2/3]
我要做回自己--Aaronyang的博客(www.ayjs.net) 博客摘要: Virtualizing虚拟化DEMO 和 大数据加载的思路及相关知识 WPF数据提供者的使用ObjectDataPr ...
随机推荐
- 主界面(零基础适合小白)基础javaweb前端项目实战【包含增删改查,mysql】三
首先编写sp文件(index.jsp) <%@ page contentType="text/html;charset=UTF-8" language="java& ...
- Google Guava提供的特殊的Table集合
1.Table 是个啥? 是一个特殊的映射,其中两个键可以在组合的方式被指定为单个值.它类似于创建映射的映射. 当你想使用多个键做索引的时候,你可能会用类似 Map<rowKey, Map< ...
- 理解 Paimon changelog producer
介绍 目的 Chaneglog producer 的主要目的是为了在 Paimon 表上产生流读的 changelog, 所以如果只是批读的表是可以不用设置 Chaneglog producer 的. ...
- python操作mongodb实现读写分离
读写分离 默认情况下,MongoClient 实例将查询发送到副本集的主要成员. 要使用副节点作为查询,以实现读写分离,我们必须更改读取首选项: 读取首选项在模块pymongo.ReadPrefere ...
- Gh0st木马
https://www.secrss.com/articles/50209 Gh0st是一种远程控制软件,它可以在被攻击的计算机上运行并允许攻击者远程控制该计算机.为了查找Gh0st的进程.文件.注册 ...
- history详解
linux下history命令详解 如果你经常使用 Linux 命令行,那么使用 history(历史)命令可以有效地提升你的效率.本文将通过实例的方式向你介绍 history 命令的 15 个用法. ...
- .NET Core Swagger Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround
遇到的问题 因为新增了一个控制器方法,从而导致在运行Swagger的时候直接报错,异常如下: SwaggerGeneratorException: Conflicting method/path co ...
- Quartz.Net系列(八):Trigger之CalendarIntervalScheduleBuilder详解
所有方法图 CalendarIntervalScheduleBuilder方法 在SimpleScheduleBuilder基础上实现了日.周.月.年 WithInterval:指定要生成触发器的时间 ...
- 【“互联网+”大赛华为云赛道】IoT命题攻略:仅需四步,轻松实现场景智能化设计
摘要:仅需四步,轻松实现场景智能化设计,作品开发超轻松. 本文分享自华为云社区<["互联网+"大赛华为云赛道]IoT命题攻略:仅需四步,轻松实现场景智能化设计>,作者: ...
- 【“互联网+”大赛华为云赛道】GaussDB命题攻略:支持三种开发语言,轻松完成数据库缓冲池
摘要:七届中国国际"互联网+"大学生创新创业大赛火热报名中,为了帮助参赛者更好了解赛题设计思路和命题方向,华为云产业命题赛道举行了线上直播解读,华为云数据库资深架构师苏斌在直播间详 ...