JS的分号可以省掉吗?
发布于 6 年前 作者 Fundebug 3857 次浏览 来自 分享

摘要: 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))

然后执行看看结果如何:

error.png

在项目中没有报错,单独将这段代码拿出来在浏览器控制台下执行却报错了!

这么简单的代码为什么会出错呢?第一反应就是JS引擎将代码生成语法树的时候,可能解析不正确。于是,我在第一行末尾加分号测试。

console.log("hello, fundebug");
[1, 2, 3].map(i=>console.log(i))

程序正确执行了:

passed.png

这让我更加犯难,如果不加分号会导致程序出错,那么为什么还会推崇这样的编码规范呢? 在网络上搜索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/

11 回复

代码 ts ,配合 tslint , eslint, 省略分号 (有歧义之处 vsc 的 tslint 插件会提示你加上分号)

文章不错。 standardJS是在强制要求其他语法规范避免出现问题的基础之上要求不写分号的,如果自己用ESLint的时候配置了此类强大的规则避免不写分号带来的问题就可以继续不写分号,盲目追求不写分号是很危险的。

参与制定ES-262的一些人表示,引进的新特性越来越多,未来一定会遇到一些希望加入的新特性是必须写分号才能正常解析的,所以长远看的话,还是养成写分号的习惯保险一些。

首先JS的分号是可以省掉,但是从可读性和可维护性来讲推荐源码还是加上分号比较好。 目前我自己参与的项目都是直接参照https://standardjs.com/readme-zhcn.html进行代码规范校验。

如果真是长远看需要加, 那就到时候再加, 这样才敏捷嘛🤨. 可读性上来说, 体验过一段时间无分号之后, 我打包票90%的人都会喜欢上无分号. 至于可维护性, 公司前后端都不用分号, 一直很顺畅嘛.

如果觉得可读性不好, 请以下面代码找茬: image.png

代码块可以省略,直接执行间不可省略 压代码时候就不报错

@xiaozhongliu 每个人的偏好不一样呐…所以这事和好看不好看没有什么关系…

表示不写分号浑身难受,不知道不写分号的好处在哪里!!!

我觉得没有分号干净很多

你是自己的项目看你喜欢怎么风格,如果是开源或者业务项目还是写上分号为好,你的风格别人并不一定喜欢,说没有分号可读性更流畅怨我无法苟同

@manyuewuxin 认同!风格各有偏好没啥好说的。只要团队统一木有BUG就没事

回到顶部