JS的分号可以省掉吗?
摘要: JavaScript语言从设计之初就是考虑带分号的,使用不带分号的编码规则就要小心点啦。
背景
最近在项目中开始使用新的编码规范,一开始ESLint报一大堆错误,改得我想砸键盘,花了好些时间才适应,下面列出一些代表性的规则:
- 只能使用单引号
- 函数定义的圆括号和左大括号之间一定要有空格:
function(args) { .. } - import语句在大括号之后一定要有空格:
import { fa, fb } from moduleC - 不用分号!!!
起因
早上在实现一个功能的时候,写了一个map函数来复用部分代码。程序运行起来后,没有执行结果,而且没有报错。通过console.log打印数据发现,整个程序执行到map前面就再也不往下走了,很奇怪。因为没有报错信息,无法推测具体原因。于是,我将其抽象成非常简单的代码来排查。如下所示:
console.log("hello, fundebug")
[1, 2, 3].map(i=>console.log(i))
然后执行看看结果如何:

在项目中没有报错,单独将这段代码拿出来在浏览器控制台下执行却报错了!
这么简单的代码为什么会出错呢?第一反应就是JS引擎将代码生成语法树的时候,可能解析不正确。于是,我在第一行末尾加分号测试。
console.log("hello, fundebug");
[1, 2, 3].map(i=>console.log(i))
程序正确执行了:

这让我更加犯难,如果不加分号会导致程序出错,那么为什么还会推崇这样的编码规范呢?
在网络上搜索JavaScript关于分号的BUG,发现有非常多关于要不要使用分号的讨论。
大宗师Douglas Crockford表示要正确使用分号
引用minhan在扯不完的 JS 分号问题文中的论述:
JSON、JSLint、JSMin和ADSafe 的创造者、ECMA JavaScript 2.0 标准化委员会委员、被JavaScript之父Brendan Eich称为JavaScript的大宗师、名著《JavaScript: The Good Parts》(中文版《JavaScript语言精粹》)的作者Douglas Crockford直接怼之: 这代码真尼玛的疯狂傻X,我是不会为了这傻X的案例而去降低JSMin的级数; TC39正在考虑将『!』号作为中缀运算符使用,这个代码不久将来就运行不了。赶紧修复吧,学学怎么正确地使用分号。『!』号并不语句的分隔号,『;』才是。
JSMin处理如下代码后无法正确执行:
clearMenus()
!isActive && $parent.toggleClass('open')
自动分号插入机制
JavaScript有着自动分号插入的机制(Automatic Semicolon Insertion),简称ASI。这是一个辅助性的功能,然后有一些情况要注意:
如果你这样写代码:
return
a + b
那么自动分号插入后会这样:
return;
a + b;
更可能导致隐含BUG的状况是:
a = b + c
(d + e).print()
他不会自动插入分号,因为第二行一括号开始,会被误认为是函数。
a = b + c(d + e).print();
所以,我刚刚的的代码在自动插入分号后,应该是这样:
console.log("hello fundebug")[1,2,3].map(i=>console.log(i))
那么这样看来,用分号才是最安全的做法咯!
如果你不想用分号,又怕出问题,v2ex上有位童鞋给出了一个速记方案:
如果你写 JS 代码不喜欢带分号,而又搞不清什么时候必须加分号,可以这么做:在以 "("、"[" 、"/"、"+"、"-" 开头的语句前面都加上一个分号。
我最终的解法是先声明一个变量来指向这个数组,这样就可以避免以[开头,又不使用分号:
let indexArray = [1, 2, 3]
indexArray.map(i=>console.log(i))
关于Fundebug
Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了6亿+错误事件,得到了Google、360、金山软件等众多知名用户的认可。欢迎免费试用!
转载时请注明作者 Fundebug以及本文地址:
https://blog.fundebug.com/ 2018/09/18/js-semicolon-bug/
JS的分号可以省掉吗?的更多相关文章
- 如果您想省略JS里的分号,了解一下JS的分号插入原理吧
仅在}之前.一个或多个换行之后和程序输入的结尾被插入 也就是说你只能在一行.一个代码块和一段程序结束的地方省略分号. 也就是说你可以写如下代码 function square(x) { var n = ...
- Js中分号使用总结
作者:尤雨溪链接:https://www.zhihu.com/question/20298345/answer/49551142来源:知乎著作权归作者所有,转载请联系作者获得授权. 没有应该不应该,只 ...
- 什么是js和js的基本语法
时间:2016年12月15日 先讲讲基础语法: 大部分是来操作表单: js动态效果和数据交互(ajax?) js也有自己的API js大部分的DOM操作都是针对input的. 案例学习,对注册页面的简 ...
- 《JS权威指南学习总结--第二章词法结构》
第二章词法结构 内容要点: 一.注释 1. //表示单行注释 2. /*这里是一段注释*/ 3.一般编辑器里加注释是:选中要加注释的语句,按 ctrl+/ 二.直接量 所谓直接量,就是程序中直接使用的 ...
- 从零开始的JS生活(一)——JS简介、变量及基本结构
本K在经过三个静态站制作的狂风暴雨之后,终于开始了JavaScript的学习.作为一只从来没有正儿八经接受过计算机语言的小白,居然能够跟上浩哥的课程进度,我的内心都被我的才智震惊到了,果然本K是天生丽 ...
- JS相关重点知识 (概况)
1.value和innerHTML没有联系,只是value是表单的一个特有属性,而innerHTML是通用的. 2.当从外部引入js文件时,该外部文件里面可以有多个方法, html页面中的oncl ...
- auto semicolon insertion 自动分号补齐的坑
今天发现js自动分号补齐的坑,来看如下两段代码: function Hello(){ return { name: ’JavaScript’ }; } alert(Hello()); //输出unde ...
- js面试题总结
1.typeof和Object.prototype.toString typeof是js里面判断变量类型的一种方法,但这种方法没有Object.prototype.toString准确,前者有6种判断 ...
- js上 二.JavaScript基本语法
1.JavaScript词法结构 所谓词法结构是指一套基础性规则,用来描述如何使用这门语言来编写程序,包括如下几项: ü 字符集unicode ü 区分大小写 (true和TRUE) ü 忽略空白字符 ...
随机推荐
- C#情怀与未来
C#情怀与未来,怨天尤人还是抓住机会,能否跟上dnc新时代浪潮? 经常看到有.NET圈子在讨论是否应该转其它语言 C#情怀是一方面,如果觉得C#未来没前途,光靠情怀是撑不住的, 建议对C#未来 ...
- 用react + redux + router写一个todo
概述 最近学习redux,打算用redux + router写了一个todo.记录下来,供以后开发时参考,相信对其他人也有用. 注意: 我只实现了Footer组件的router,其它组件的实现方法是类 ...
- 30-socketserver类
SocketServer模块简化了编写网络服务程序的任务.同时SocketServer模块也是Python标准库中很多服务器框架的基础. socketserver模块可以简化网络服务器的编写,Pyth ...
- 记一次sentry部署过程
本文记录下部署sentry和其中遇到的问题 Sentry 是一款基于 Django实现的错误日志收集和聚合的平台,它是 Python 实现的,但是其日志监控功能却不局限于python,对诸如 Node ...
- Zabbix系列之三——部署JMX监控tomcat
zabbix提供了一个java gateway的应用去监控jmx(Java Management Extensions,即Java管理扩展)是一个为应用程序.设备.系统等植入管理功能的框架.JMX可以 ...
- JVM 监控,调优,调试
JVM监控工具 Java的安装包自带了很多优秀的工具,善用这些工具对于监控和调试Java程序非常有帮助.常用工具如下: jps 用途:jps用来查看JVM里面所有进程的具体状态, 包括进程ID,进程启 ...
- mysql 开发进阶篇系列 39 mysql日志之二进制日志(binlog)
一.概述 二进制日志(binlog)记录了所有的DDL(数据定义语言)语句和DML(数据操纵语言)语句,但是不包括数据查询语句, 语句以"事件"的形式保存,它描述了数据的更改过程, ...
- 使用Dockerfile制作JDK+tomcat镜像
1.准备好jdk和tomcatapache-tomcat-8.5.32.tar.gzjdk-8u181-linux-x64.tar.gz 注意:a.jdk和tomcat记得从官网下载,否则制作出来的镜 ...
- LoadRuner12.53教程(二)
使用HP Web访问示例应用程序 shǐ使 yòng用 H P W e b fǎng访 wèn问 shì示 lì例 yìng应 yòng用 chén ...
- Linux 强制安装 rpm 包
Linux 正常安装 rpm 的命令是: rpm -ivh xxx.rpm 重复安装时需加属性: 软件包重复安装将会失败,若仍需要安装必须加 --replacepkgs 属性 软件包的某个文件已在安装 ...