5.3 自动分号
有时 JavaScript 会自动为代码行补上缺失的分号,即自动分号插入(Automatic Semicolon Insertion,ASI)。
因为如果缺失了必要的 ; ,代码将无法运行,语言的容错性也会降低。ASI 能让我们忽略那些不必要的 ; 。
请注意,ASI 只在换行符处起作用,而不会在代码行的中间插入分号。
如果 JavaScript 解析器发现代码行可能因为缺失分号而导致错误,那么它就会自动补上分号。并且,只有在代码行末尾与换行符之间除了空格和注释之外没有别的内容时,它才会这样做。
例如:
var a = 42, b c;
如果 b 和 c 之间出现 a , 的话(即使另起一行),c 会被作为 var 语句的一部分来处理。在上例中,JavaScript 判断 b 之后应该有 ; ,所以 c; 被处理为一个独立的表达式语句。
又比如:
var a = 42, b = "foo"; a b // "foo"
上述代码同样合法,不会产生错误,因为 ASI 也适用于表达式语句。
ASI 在某些情况下很有用,比如:
var a = 42; do { // .. } while (a) // <-- 这里应该有; a;
语法规定 do..while 循环后面必须带 ; ,而 while 和 for 循环后则不需要。大多数开发人员都不记得这一点,此时 ASI 就会自动补上分号。
本章前面讲过,语句代码块结尾不用带 ; ,所以不需要用到 ASI:
var a = 42; while (a) { // .. } // <-- 这里可以没有; a;
其他涉及 ASI 的情况是 break 、continue 、return 和 yield (ES6)等关键字:
function foo(a) { if (!a) return a *= 2; // .. }
由于 ASI 会在 return 后面自动加上 ; ,所以这里 return 语句并不包括第二行的 a *= 2 。return 语句的跨度可以是多行,但是其后必须有换行符以外的代码:
function foo(a) { return ( a * 2 + 3 / 12 ); }
上述规则对 break 、continue 和 yield 也同样适用。
纠错机制
是否应该完全依赖 ASI 来编码,这是 JavaScript 社区中最具争议性的话题之一(除此之外还有 Tab 和空格之争)。
大多数情况下,分号并非必不可少,不过 for( .. ) .. 循环头部的两个分号是必需的。
正方认为 ASI 机制大有裨益,能省略掉那些不必要的 ; ,让代码更简洁。此外,ASI 让许多 ; 变得可有可无,因此只要代码没问题,有没有 ; 都一样。
反方则认为 ASI 机制问题太多,对于缺乏经验的初学者尤其如此,因为自动插入 ; 会无意中改变代码的逻辑。还有一些开发人员认为省略分号本身就是错误的,应该通过 linter 这样的工具来找出这些错误,而不是依赖 JavaScript 引擎来改正错误。
仔细阅读规范就会发现,ASI 实际上是一个“纠错”(error correction)机制。这里的错误是指解析器错误 。换句话说,ASI 的目的在于提高解析器的容错性。
究竟哪些情况需要容错呢?我认为,解析器报错就意味着代码有问题。对 ASI 来说,解析器报错的唯一原因就是代码中缺失了必要的分号。
我认为在代码中省略那些“不必要的分号”就意味着“这些代码解析器无法解析,但是仍然可以运行”。
仅仅为了追求“代码的美观”,省去一些键盘输入,这样做不免有点得不偿失。
这与空格和 Tab 之争还不是一回事,后者仅涉及代码的美观问题,前者则关系到原则问题:是遵循语法规则来编码,还是打规则的擦边球。
换个角度来看,依赖于 ASI 实际上是将换行符当作有意义的“空格”来对待。在一些语言(如 Python)中空格是有意义的,但这对 JavaScript 是否适用呢?
我建议在所有需要的地方加上分号,将对 ASI 的依赖降到最低。
以上观点并非一家之 言。JavaScript 的作者 Brendan Eich 早在 2012 年就说过这样的话(http://brendaneich.com/2012/04/the-infernal-semicolon/ ):
ASI 是一个语法纠错机制。若将换行符当作有意义的字符来对待,就会遇到很多问题。多希望在 1995 年 5 月的那十天里(ECMAScript 规范制定期间),我让换行符承载了更多的意义。但切勿认为 ASI 真的会将换行符当作有意义的字符。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论