写给前端专家的一封公开信:关于分号(翻译)

本文作者: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 表示一个语句结束,除非出现下面几种情况:

  1. 该语句中含有未关闭的([、或 {,或者是以某种不合法的结束方式来结束(如以 . 或者 , 结束)
  2. 这一行的内容是 --++(这会使下面一行自增或自减)
  3. 这一行是 for() while() do if()else 等语句,且不带 {
  4. 下一行以 [ ( + * / - , . 或其他二元操作符开头

第一条是很显然的事情。我们在 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(受限操作)

另一个争论点是关于 Restricted Productions。如果你在 return throw break continue ++-- 后面加一个 \n,那么语句就立即结束。

// 预期
return 7
// 产生错误
return
        7

我必须再一次强调,在你改变了「在一切语句后面加分号」的习惯后,这种问题是非常容易发现和避免的。当我看见 return\n,我的大脑会立刻告诉我「这条语句已经结束了」,因为 \n 就是语句结束标记。

把相关标记放在每行行首是最适合人类快速阅读的。大量与阅读速度和眼球跟踪的研究已经说明,在每行行尾找出一个缺少的字符比在行首找难得多。所以我说,应该把重要的标记放在行首。

哪一种风格更好?

目前而言,我认为「尽量少些分号,逗号放在行首」(minimal-semicolon/comma-first)的风格略微优雅一些。不仅因为它更适合人类扫读,而且它还鼓励程序员深入了解他们所用的语言。

其实你大可不必关心我的代码风格是怎样的,反正我不关心你的代码风格是怎样的。这篇文章不是让你模仿我的代码风格,毕竟「你自己的代码只有你自己最了解」。

在所有语句后面加分号的好理由

加分号最靠谱的理由是

  • 美观:如果你写很多 Java 或 C 代码,同时不想让你的 JavaScript代码显得很不一样,那么你可以这样做。
  • 规范:如果为了团队代码的一致性,比如统一采用了 JSHint,那么也可以这样做。

糟糕的理由

「自动加分号(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语句,那么你对这门语言的了解就存在一个短板。

(译注:后面太主观了,就不翻译了)

(完)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java后端技术栈

开发中我们需要遵循的几个设计原则!

在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则和具体阐...

922
来自专栏FreeBuf

分析无线遥控器信号并制作Hack硬件进行攻击

*原创作者:ZMOM1031,本文属FreeBuf原创奖励计划,未经许可禁止转载 ? 无线遥控器(无线电遥控器)在我们生活中非常常见,应用于各种场景,方...

2698
来自专栏Dawnzhang的开发者手册

开发中我们需要遵循的几个设计原则!(转)

在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则和具体阐...

1292
来自专栏Java面试通关手册

一份送给Java初学者的指南

我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailc...

1463
来自专栏Java面试笔试题

简述一下面向对象的”六原则一法则”

1122
来自专栏牛客网

听说有人想要爱奇艺面经?

1910
来自专栏小小挖掘机

数据城堡参赛代码实战篇(三)---我们来探究一个深奥的问题!

每天12点是小编最激动的时候,因为自己写的帖子又可以与大家见面啦,昨天把帖子传到某个大神组织的数据挖掘交流群时,某挖掘机朋友问了小编一个深刻的问题,题目看似很简...

3475
来自专栏圣杰的专栏

DDD理论学习系列(7)-- 值对象

? 1.引言 提到值对象,我们可能立马就想到值类型和引用类型。而在C#中,值类型的代表是strut和enum,引用类型的代表是class、interface、...

2737
来自专栏章鱼的慢慢技术路

2017年第八届蓝桥杯C/C++B组省赛题目解析

3845
来自专栏微信公众号:Java团长

开发中我们需要遵循的几个设计原则!

在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则和具体阐...

971

扫码关注云+社区