34

JS的分号可以省掉吗?

 5 years ago
source link: https://blog.fundebug.com/2018/09/18/js-semicolon-bug/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

摘要:JavaScript语言从设计之初就是考虑带分号的,使用不带分号的编码规则就要小心点啦。

背景

最近在项目中开始使用新的编码规范,一开始ESLint报一大堆错误,改得我想砸键盘,花了好些时间才适应,下面列出一些代表性的规则:

function(args) { .. }
import { fa, fb } from moduleC

起因

早上在实现一个功能的时候,写了一个 map 函数来复用部分代码。程序运行起来后,没有执行结果,而且没有报错。通过console.log打印数据发现,整个程序执行到map前面就再也不往下走了,很奇怪。因为没有报错信息,无法推测具体原因。于是,我将其抽象成非常简单的代码来排查。如下所示:

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

然后执行看看结果如何:

FzMfArU.png!web

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

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

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

程序正确执行了:

NZ7fIvZ.png!web

这让我更加犯难,如果不加分号会导致程序出错,那么为什么还会推崇这样的编码规范呢?

在网络上搜索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、金山软件等众多知名用户的认可。欢迎免费试用!

MJ3Mzyy.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK