本文作者:IMWeb frankfang 原文出处:IMWeb社区 未经同意,禁止转载
Sean Silva 给我发来一封信:
我最近在浏览你 npm.js 项目里的代码(代码链接),很喜欢你的代码风格: 你把逗号放在行首,与上一行 var 中的 r 对齐,或者与上一行的
[
和{
对齐。但是我不是很敢学的你风格,因为很多 JS 教材都说 JS 解释器的自动加分号机制会对代码有影响。 如果我不把逗号放在行尾,而是放在下一行行首,在浏览器里是否安全呢?抑或是说只能在 Node 里这样用呢? 2011年11月20日
我回复道:
是的,这样是安全的,而且是完全合法的 JS,每个浏览器都理解。Closure、yuicompressor、packer 和 jsmin 都可以完美地压缩这样的 JS。而且也不存在性能影响。 遗憾的是,前端社区的一些专家散布谎言和恐惧,却没有真正地指导新人。我推荐新人去了解 JS 语句是到底是怎么「断句」的,那样才能写出自己认为优美的代码。
Inimino 的文章《JS 分号必知必会》对此解释得很清楚,他本人对是否添加分号持保留意见,但我打算更主观一些。
一般地,\n
表示一个语句结束,除非出现下面几种情况:
(
、[
、或 {
,或者是以某种不合法的结束方式来结束(如以 .
或者 ,
结束)--
或 ++
(这会使下面一行自增或自减)for()
while()
do
if()
或 else
等语句,且不带 {
[ ( + * / - , .
或其他二元操作符开头第一条是很显然的事情。我们在 JSON 里经常用到类似的断句方式,在一个 var
语句里声明多个变量时也会用 ,
来断句。
第二条就比较奇怪。假设我们写 i\n++\nj
,结果得到的是 i; ++j
,却不是 i++; j
。
第三条很好理解。if (x)\n y()
会被认为是 if (x) {y()}
。
第四条是我们恐惧的诱因:「不行,你一定要加上分号,不然下一行的二元操作符会引发问题的!」但是,如果下一行不想影响上一行,只要在行首加一个分号就能解决问题。比如
foo();
[1,2,3].forEach(bar);
可以写成
foo()
;[1,2,3].forEach(bar)
这样写的好处是行首分号更容易引起注意,而且你会习惯于在以 (
和 [
开头的语句前面加上分号。
另一个争论点是关于 Restricted Productions。如果你在 return
throw
break
continue
++
或 --
后面加一个 \n
,那么语句就立即结束。
// 预期
return 7
// 产生错误
return
7
我必须再一次强调,在你改变了「在一切语句后面加分号」的习惯后,这种问题是非常容易发现和避免的。当我看见 return\n
,我的大脑会立刻告诉我「这条语句已经结束了」,因为 \n
就是语句结束标记。
把相关标记放在每行行首是最适合人类快速阅读的。大量与阅读速度和眼球跟踪的研究已经说明,在每行行尾找出一个缺少的字符比在行首找难得多。所以我说,应该把重要的标记放在行首。
目前而言,我认为「尽量少些分号,逗号放在行首」(minimal-semicolon/comma-first)的风格略微优雅一些。不仅因为它更适合人类扫读,而且它还鼓励程序员深入了解他们所用的语言。
其实你大可不必关心我的代码风格是怎样的,反正我不关心你的代码风格是怎样的。这篇文章不是让你模仿我的代码风格,毕竟「你自己的代码只有你自己最了解」。
加分号最靠谱的理由是
「自动加分号(ASI)不靠谱。」
真的吗?
这话在 JavaScript发展的早期,也就是 90 年代,就有很多人说。在我看来这种自称 JavaScript专家却对 JS 断句机制不了解的人是不可原谅的,像他们这样散布未经证实的观点也是极不负责任的。
而且,他们所谓不靠谱都与 Restricted Productions 有关,在所有地方加分号只会让 return\n7
变成 return;7;
,真正的问题在于你乱加回车,而不是分号。
唯一的解决办法是别用回车(\n
),全部都用分号。(译注:那岂不是所有代码都在一行了。)但是不会有人建议这样做。所以不要再拿 return 的例子来说自动加分号的坏话了,如果你不了解 ASI 的话你就承认自己在滥用分号就好了。你只有在了解了 ASI 之后才有资格说自己是一个 JavaScript开发者,就这样。
如果你不了解 JS 的断句机制,那么你就对 JS 掌握的不太好,也不应该在没有指导的情况下写 JS,而且你也不应该指导任何人写 JS。
我猜我已经冒犯到你了。很不幸,虽然我知道你可能已经掌握了 JS 周边的很多知识,比如 DOM,比如 CSS,比如 IE 的兼容技巧,还有 jQuery。可能你也已经花了一些时间学习闭包、原型、作用域和活动对象,甚至还给 V8 和 SpiderMonkey 写过扩展。我知道你很聪明,或许比我聪明多了,也比我帅,说不定我们有很多共同点,还能成为朋友。
但是,如果你不是真正的了解 JavaScript语句,那么你对这门语言的了解就存在一个短板。
(译注:后面太主观了,就不翻译了)
(完)