JavaScript 的分号补全问题

在 JavaScript 中,一个语句(statement)以分号结尾。如果省略分号,则按照 ECMAScript 的规范来确定语句的结尾。在 ECMAScript 规范说明,对于下列这些语句,如果没有分号,解析器将会自动添加分号到合适的位置:

  1. 空语句
  2. 变量语句
  3. 表达式语句
  4. do-while 语句
  5. continue 语句
  6. break 语句
  7. return 语句
  8. throw 语句

分号自动添加的规则有如下三条:

一、解析器碰到文件的结尾。

二、解析器遇到不合语法的符号(token),而且 (a) 这个符号和前面的符号之间有换行符;或者 (b) 这个符号就是 }。

三、解析器遇到下列五种 restricted productions,而且后面有换行符

  1. 后缀表达式 ++ 和 --
  2. continue 语句
  3. break 语句
  4. return 语句
  5. throw 语句

第一条规则容易出现的问题在使用工具合并 JavaScript 文件时,两个文件都是正确的,但是第一个文件的最后一行没有行尾分号和换行,合并后它将和第二个文件的首行连接起来,导致合并的文件是错误的。

第二条规则容易出现的问题在后面代码和前面代码合起来也符合语法的时候,例如:

var fun = function(){
  return function() {
    console.log("1");
  }
}

(function(){
  console.log('2');
})()

这时候,在前面代码后面将不会自动添加分号,导致两部分连接起来,输出的结果是 1 而不是 2。一般地,我们应该注意行首的 ([+-/ 这五个符号,因为它们可能和上面的代码连接起来,导致错误。

第三条规则容易出现的问题在 return 后换行的时候。例如:

function() {
  return
  {
     i: 1,
     j: 2
  };
}

这时候 return 后面将自动添加分号,使得返回值为 undefined,而不是一个对象。

自动添加分号的具体规则可以看 ECMAScript 规范。

参考资料:

[1] ECMAScript 5.1 Language Specification - #Automatic Semicolon Insertion

[2] Javascript的10个设计缺陷 - 阮一峰的网络日志

[3] JavaScript语句后应该加分号么? - hax的技术部落格 - ITeye技术网站

[4] JavaScript Semicolon Insertion

[5] Dealing with JavaScript's Automatic Semicolon Insertion

[6] Expressions versus statements in JavaScript