摘要:
JavaScript语言从设计之初就是考虑带分号的,使用不带分号的编码规则就要小心点啦。
背景
最近在项目中开始使用新的编码规范,一开始ESLint报一大堆错误,改得我想砸键盘,花了好些时间才适应,下面列出一些代表性的规则:
起因
早上在实现一个功能的时候,写了一个
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。这是一个辅助性的功能,然后有一些情况要注意:
如果你这样写代码:
那么自动分号插入后会这样:
更可能导致隐含BUG的状况是:
他不会自动插入分号,因为第二行一括号开始,会被误认为是函数。
a = b + c(d + e).print();
|
所以,我刚刚的的代码在自动插入分号后,应该是这样: