为什么最近转向从Java脚本中删除/省略分号?


79

最近,从Java语言中省略分号似乎很流行。几年前有一篇博客文章强调,在Javascript中,分号是可选的,并且文章的主旨似乎是您不必理会它们,因为它们是不必要的。该帖子被广泛引用,并没有给出任何令人信服的理由使用它们,只是将它们排除在外几乎没有副作用。

甚至GitHub都跳上了无分号的潮流,要求它们省略任何内部开发的代码,并且其维护者最近对zepto.js项目的承诺已从代码库中删除了所有分号。他的主要论据是:

  • 这是他团队的优先事项;
  • 打字少

还有其他好的理由将其排除在外吗?

坦白说,我看不出没有理由忽略它们,当然也没有理由回过头来删除它们。这也违背了(多年的推荐做法,我并不真的赞成“货运崇拜”的说法。那么,为什么最近都讨厌分号?短缺迫在眉睫吗?还是这只是最新的Javascript时尚?


2
“几年建议的做法的”指的问题列入黑名单 SO投票标签这不可能使它权威支持任何一种意见认为
蚊蚋

24
@gnat只是因为人们讨厌SO上的问题并不能使它成为人们观点的较无效来源。
Ryathal

3
@gnat 有时 “专家认为在StackOverflow上不合适的问题” 非常权威的。悲伤但真实。
MarkJ 2012年

4
@gnat列入黑名单的问题实际上有一些非常有趣的示例,说明了为什么省略;可以破坏您的代码。因此,我想这是对这个问题的有用参考。
Andres F.

1
这可能与2010年代初期时髦人士的兴起越来越重要有关。
亚历克斯(Alex)

Answers:


61

我想我的理由是最无聊的:我同时用太多不同的语言(Java,Javascript,PHP)编程-需要';' 而不是训练我的手指和眼睛,是不需要javascript的,我只是总是添加';'

另一个原因是文档:通过添加“;” 我明确地对自己说,我希望声明会在哪里结束。然后我也一直使用{}。

我发现整个字节数参数令人讨厌且毫无意义:

1)对于通用库,例如​​jquery:使用google CDN,该库可能已经在浏览器缓存中

2)版本您自己的库,并将其设置为永久缓存。

3)gzip,如果确实需要,请最小化。

但是,实际上有多少个网站的最大下载速度瓶颈是其javascript的下载速度?如果您在Twitter,Google,Yahoo等排名前100的网站工作,也许吧。我们其余的人应该只担心代码质量而不是分号宗教战争。


3
我猜相反也可能是正确的。随着python在网络上越来越流行,让您的JS类似于python变得更加容易。
Ben DeMott

4
尝试,但是同一行的字节战士会在我后面追逐不必要的行首空格。(我还会遇到Javascript错误,因为我将依赖于Python的缩进规则,而不是使用{}
Pat

6
如果减少字节数很重要,那么您将拥有尽可能减少文件数量的功能。如果还不值得使用最小化器,那么就不必担心删除';'了。以节省字节数。
Lawtonfogle

3
字节数实际上并不一定要减少,实际上它实际上可以增加,因为换行通常(并非总是)实际上是两个字符(换行后跟回车符),因此以最节省空间的形式该行将一次与一个字符的分号相同(如果将所有JS代码压缩为一行,这通常是针对已部署的JS代码而不是开发源代码完成的)。
ALXGTV 2015年

人类需要缩进来理解深度嵌套,深度嵌套比分号需要更多的字节。分号正在分散按键的浪费。
Cees Timmerman

39

它使方法链接更容易,提交差异更清晰

假设我正在使用jQuery,

$('some fancy selector')
  .addClass()
  .attr();

如果我想添加内容并使基于行的提交差异保持较小,则必须将其添加到attr上方。因此,比“最后添加”要花更长的时间。谁想思考?=)

$('some fancy selector')
  .addClass()
  // new method calls must go here
  .attr();

但是,当我删除分号时,我可以追加并称之为一天

  $('some fancy selector')
    .addClass()
    .attr()
+   .animate()
+   .click()

另外,如果我决定退出最后一种方法,则不必重新分配分号并再次污染我的提交。

  $('some fancy selector')
    .addClass()
    .attr()
    .animate()
-   .click()

与uggo

  $('some fancy selector')
    .addClass()
    .attr()
+   .animate();
-   .animate()
-   .click();

37
这是利基用例IMO。
JBR威尔金森

9
但是有趣的是。
乔纳森(Jonathan)2012年

8
您可以在缩进起始行的新行末尾使用分号。然后,您可以根据需要复制并重新排序。这也很好地关闭了连锁店。
Nux

11
只是我想知道为什么有人会关心提交内容的差异如何整洁吗?通常,人们阅读代码,而不是差异。
Jules 2014年

11
@Jules,差异较大的合并意味着合并更有可能成功。
joeytwiddle

22

JavaScript中的分号是可选的

我个人不使用半冒号的原因是OCD。

当我使用半冒号时,我会忘记其中的2%,并且必须不断检查/添加回去。

当我不使用半冒号时,我永远不会偶然插入半冒号,因此我不必检查/移除它们。


3
好一个 我已经在没有其他分号的文件中被一两分号的小分号灼伤了。
乔纳森(Jonathan)

3
如果没有分号,解析器(例如GeSHi)将无法正确解析您的代码。您可能会说人类不会犯这样的错误……但是,很严重-如果您的所有团队都能记住绝对需要在何处放置分号,您是否真的会认为没有早上喝咖啡就会记住它?他们将以多种状态进行编码。一定要
Nux

16

我最近为JavaScript编写了一个解析器/分析器,在那里我不得不辛苦地实现ASI,并且我的书架上也有Crockford的JavaScript:The Good Parts的副本,该书主张始终使用分号。意图是好的,但在实践中并不总是有帮助。

显然,编写jQuery,zepto等框架的人是JavaScript语法大师,因此他们知道以下两者之间的区别:

return
{
    status: true
};

return {
    status: true
};

JavaScript虽然功能强大,但它也是初学者的语言,祝您好运,向刚刚学习for循环的人解释这一点。就像向大多数人介绍一种新技能一样,您不想立即解释一些更复杂的事情,因此,您选择对某些事情灌输“货运邪教”的信念,只是为了让他们起步。因此,在教初学者如何编写JavaScript时,您有两种选择:

  1. 告诉他们“遵循这一规律,不要问为什么”,告诉他们把一个总是在每行的末尾分号。不幸的是,这对上面的示例或任何其他妨碍ASI的示例都没有帮助。当上面的代码失败时,初学者程序员会感到困惑。
  2. 告诉他们“遵循这两个规则,不要问为什么”,告诉他们不要在每行的末尾打扰分号,而是总是 a)跟随returna {和b)当一行以a开头时(,在前面加上它带有一个;

选择选项2是要遵循的一组更好的“货物崇拜”规则(将导致很少的与ASI相关的错误),并且即使您对主题有深入的了解,屏幕上不需要的字符也会更少。


8
好吧,我咬。帮助我了解以上两个示例在语法上的区别。我未经训练的眼睛只会看到格式上的差异。
Jesse C. Slicer 2012年

9
或者,另一方面,由于偶然的意外,我偶然发现了答案。在第一个示例中,return视为单行陈述,并且行尾与分号等效。第二个示例实际上返回该对象。调皮。
Jesse C. Slicer 2012年

9
我不同意JavaScript是一种初学者的语言,在JavaScript中有很多不一致之处和令人惊讶的效果,但这些解释并没有简单的解释。IMO不是初学者的语言,我将JavaScript称为中间语言。
Ryathal 2012年

2
@Ryathal我了解您的意思,但是将其称为中间语言会让我想知道它所中介的语言。您听起来好像是在迈向其他目的而非自己的目的地。
拉切特

9
澄清点:该return示例实际上是正常JS行为的一个例外,该行为是在省略分号时尝试将行合并在一起。 return,,breakcontinue都表现出这种异常行为,其中尾随换行符始终被解释为语句的结尾。(来源是Flanagan的“ JavaScript:权威指南” pp25-26)。就我个人而言,我努力实现“最少惊喜的代码”的想法。遗漏分号往往会带来比任何东西都更多的惊喜(即使对于简单的陈述,我通常也会保留大括号)。
凯尔(Kyle)

16

没有信息过载,只有糟糕的设计。

—爱德华·塔夫特

减少不必要的元素和装饰是减少噪声的图形设计一般规则

屏幕上的视觉元素更少,意味着我们的大脑需要更少的工作来解析实际的有用信息。

let foo = 1

let /* variable */ foo = 1; // EOL

当然,这是一个夸张的示例,但它说明了一般原理:当且仅当有视觉目的时,才应添加其他视觉元素。那么,分号是否有目的?

在JavaScript中使用分号的历史原因是:

  • 保持与C / Java的相似性
  • 避免与编写不良的浏览器和工具的兼容性问题
  • 帮助人和机器检测代码错误
  • 自动分号插入会导致性能下降

兼容性问题今天几乎不是问题。现代棉短绒可以检测到任何代码中的错误一样好没有分号。与C / Java / PHP的相似性仍然是一个考虑因素(请参见Pat 接受的答案),但是仅仅因为其他语言包含多余的语法元素并不意味着我们应该将其保留在JavaScript中,尤其是由于许多其他语言(咖啡,Python, Ruby,Scala和Lua)不需要它们。

我进行了快速测试,以查看V8是否存在性能下降。这是Io.js解析一个41 MB的JavaScript文件(Lodash重复了100次),并带有分号,然后删除了分号:

$ time node lodashx100.js
node lodashx100.js  2.34s user 1.30s system 99% cpu 3.664 total
$ time node lodashx100s.js
node lodashx100s.js  2.34s user 1.15s system 99% cpu 3.521 total

每个人都必须为自己的项目决定自己喜欢的编码样式,但是我不再看到使用分号的任何实际好处,因此,为了减少视觉噪音,我已经停下来了。


我会反对在负载中省掉不必要的元素的说法,现在必须要做的就是添加可选语法。现在,如果省略,分号已不是很大的精神负担。这是我在Ruby和Scala中遇到的问题。当它变成一连串的呼叫,并且呼叫内部都有呼叫时,并且它们都省略了每个括号,这是分担的负担。
Seamus

8

选择编程约定实际上与选择目标语言的子集相同。我们之所以这样做是出于通常的原因:代码的可读性,可维护性,稳定性,可移植性等-同时可能会牺牲灵活性。这些原因是真实的业务原因。

诸如“节省击键次数”和“程序员应学习JavaScript规则”之类的原因是边际业务原因,因此它们几乎没有实用价值。

就我而言,我需要非常快地提高JavaScript的速度,因此利用有限的一部分语言对我来说是有利的。因此,我选择了JavaScript的JSLint子集,将Eclipse中的Rockstar应用程序JSLinter设置为我可以忍受的最严格的设置,并且没有回头。

我很高兴能够避免出现“ ==”和“ ===”之间的区别的详细信息,或者分号插入的详细信息,因为我已经有了一个非常高的任务列表,而这些详细信息不会帮助将这些工作提前一秒钟完成。

当然,关于约定的最重要的事情是一致性,将其视为语言子集有助于加强这一必要性。尽管这可能无法回答OP的问题,但我认为这可能有助于对其进行实用的构架。


5

很老的问题,但是我很惊讶没有人提到:

缩小:如果您恰巧缩小了一个未明确用分号结尾的语句的JavaScript代码段,则可能很难找出在压缩之前就可以正常工作的代码段到底有什么问题现在不起作用。

歧义:分号是可选的,是正确的,但是通过从源代码中删除分号,您可能会将一些模棱两可的情况留给解析器自行决定。如果您要为在线商店编写100行代码,是的,也许没关系,但是更严格的任务将要求100%的清晰度。

很久以前,我读到了一个很好的比喻,但在这种情况下也是如此:(在我们的案例中)消除分号就像是闯红灯。最终您可能会没事,或者可能被卡车撞到。

为什么这些天变得越来越流行?

我个人认为让JavaScript在服务器端运行会对JavaScript社区本身产生很多影响。在我们的例子中,显然没有人会在服务器端缩减JavaScript(因为源代码不应该发送到客户端的Web浏览器),因此没有分号看起来更安全,这是事实。但是,从这些书,文章和视频中学习的其他开发人员不幸地忽略了服务器端JavaScript与客户端JavaScript不完全相同的事实。


缩小符可以保留单字符换行符,也可以在不存在分号的情况下插入分号而不会造成大小损失。我不知道哪个(如果有的话)缩小器会这样做。至少其中一些仍然存在危险,因此您的观点在实践中仍然成立。
2015年

3

有充分的理由保留它们。

它们并不是真正的可选,当它们丢失时,JS可以通过自动分号插入将它们重新添加回去,但这不是同一回事。

道格拉斯·克罗克福德(Douglas Crockford)的JavaScript:The Good Parts在两个不同的场合都说这是一个坏主意。自动分号插入会隐藏程序中的错误并造成歧义。

JSLint不赞成。


3

十多年来,JavaScript不需要分号来终止语句。那是因为换行符被认为是语句终止符(我相信早期的ECMAScript规范中也提到了这一点)。这确实很有意义,尤其是因为[我所知道的]确实没有充分的理由[为什么]为什么JavaScript需要频繁使用分号而不需要其他解释性声明性语言(如Ruby或Python)。

要求使用分号可能会更容易为一种语言编写解析器,但是如果那里的每个解释器都支持省略分号,那么这到底是什么意思呢?

归结为程序员的知识渊博:如果您知道可以省略分号,请随意这样做,以了解可能有或没有后果。人类是决策的机器,几乎所有决策都需要某种折衷或权衡。权衡一下,只是在您的代码周围(甚至在不需要它们的地方)抛出分号,这是因为您的代码变得不太可读(取决于您询问的人),并且JSLint不会抱怨(谁在乎) )。另一方面,要舍弃分号的权衡是这样一个事实,即90%的JavaScript程序员都会为此而cha之以鼻,但是由于它,您最终可能会更喜欢编写JavaScript。

对您来说听起来更好;做出明智的决定还是盲目的决策/群体心理?


我很想知道为什么这收到了反对票。JavaScript不需要分号来终止语句。它当然可以使用它们,但绝不是必需的。如果需要它们,那么没有其他人的解释会起作用。您可以(几乎没有分号)编写整个JavaScript应用程序这一事实(是的,事实)证明了这一点。除此之外,我看不出如何理解工具的工作方式以及如何使用自己的推理来做出决策与“只做它”相比有点令人反感。那就是所谓的宗教。
拉文斯汀

我没有投票,但问题可能是事实实际上并不正确。在JavaScript中,换行符不被视为语句终止符。由于称为自动分号插入的功能,您可以省去分号,该功能使它可以在某些情况下自动修复解析错误。提倡分号的人认为,许多JavaScript程序员似乎对这条规则不太了解。从这个角度来看,您的帖子似乎是对他们有利的一个论点。(公平地说,我大体上同意您的论点,但出于不同的原因)
Tim Seguine

@TimSeguine是的,我回想起之前写了这篇文章。我仍然认为,不使用分号只是客观上的错误,只要这样做的人知道他们在做什么。我应该重做我的帖子,或者因为其他足够多的人对此发表意见,所以应该删除它。感谢您的礼貌批评!:)
拉文斯汀

2

我有两种理论:

一种)

关于这种选择的事情是,在过去,当JSLint等适用时,您选择花费大量时间来捕获晦涩的语法错误,或者花费相当多的时间来执行代码标准策略。

但是,随着我们朝着单元测试驱动的代码和持续集成的方向发展,捕获语法错误所需的时间(和人工交互)已大大减少。来自测试的反馈将迅速表明您的代码是否按预期运行,并且早在接近最终用户之前,所以为什么浪费时间添加可选的详细信息?

B)

懒惰的程序员会在短期内做任何事情来使自己的生活更轻松。减少打字->减少精力->更容易。(此外,不必使用分号来避免使右手无名指紧张,避免出现RSI感)。

(注:我不同意省略一些使陈述含糊的内容的想法)。


1
jshint仍然是重要的工具。
雷诺斯2012年

至于消除歧义的陈述,两者\n;\n都相同
雷诺斯(Raynos)2012年

2
@Raynos实际上,我发现JSLint在我经常使用的一些框架繁重的代码的复杂性方面似乎毫无用处。另外,; \ n和\ n并非在所有情况下都相同,否则就永远不需要;。
Ed James

7
jslint没用,但是jshint是另一种工具。
雷诺斯2012年

0

我不会遗漏它们,但是会在插入它们时更改规则。

大多数人使用的规则是

  • 每行结束之前
  • 除了该行以}来自函数语句的结尾
  • 但是只有一个函数语句,而不是赋给函数文字

我的规则是:在每行的开头,从左括号/括号开始。

矿井更简单,因此更易于遵循,并且不易出现错误。同样,分号数量少,也很容易找到由于遗漏而产生的错误。


另一个争论是臭名昭著的return\nvalue错误来自对ASI的不了解。我的规则会强迫您了解ASI,因此使用我的规则的人不太可能陷入该错误的陷阱。


0

字节数。您会发现,恶意人员通常会尝试将大量代码放入一行代码中。从技术上讲,没有分号是不可能的。我的猜测是,它不仅仅是一种程序要求,更是一种安全措施。不知何故,当XSS成为需求而不是建议时,它将大大减少XSS。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.