ASI(Automatic semicolon insertion,自动分号插入) 机制是 JavaScript 具有标志性的一个编译规则,和其他主流类 C 语言有着显著不同。本文简述 ASI 机制规则。

语句和表达式

语句(Statement)一般指程序当中的执行单元,表达式(Expression)则侧重数据的计算和表示。在程序中,语句可以包含表达式,表达式单独也可作语句使用。如下:

  const a = 1;   // 赋值语句
  const b = i => i++;  // 箭头函数表达式 省略 return 语句
  // 其中 i++ 是自增运算表达式
  const c = b(a); // 赋值语句

表达式一般形式包括数据计算、函数表达式和对象属性、方法的调用等。

在 JavaScript 语言中,除一些制定情况外,程序语句默认使用分号作断句符(EOS, End of statement)。不受这条规则限制的特殊情况包含:

  • for/for..in/for...of/while 等循环结构
  • if/if...else/if...elseif/switch/try/try...catch 等分支结构
  • 函数声明语句(不同于函数表达式)

EOS 直接关系到程序编译工作的进行,一般在编译器读取到 EOS 后,会将该语句视作已完成。在很多传统类 C 语言当中分号是必不可少的,缺少分号在编译时将会报告错误。在 JavaScript 中,EOS 不再是必须存在的内容,编译器在处理代码时将根据语句的实际情况进行处理,并不严格依赖手动插入的分号。这个 JavaScript 特色的处理机制就是 ASI。

ASI 规则

ASI 处理代码时遵照两个基本原则:其一,换行将会触发检查;其二,分列多行的语句将会被整合。

“自动插入分号”机制并非真的在代码中插入分号,而是在符合规则的情况下,将没有分号的断句识别出来,而后按照一般的规则进行处理。可以理解为符合 ASI 的条件时,“如同” 此处有分号进行后续处理。这一机制使得 JavaScript 在代码组织上更为灵活多样。

非法语句

当下一行与上一行的语句合并后,产生的是非法语句时,在上一行语句结束位置插入 EOS 处理。

  if(status) a = 1
  console.log(a)

这个样例当中没有使用分号,但在下句向上句整合时会产生非法语句,故编译器处理时会按以下代码处理:

  if(status) a = 1;
  console.log(a);

break/continue/throw/return 语句

break/continue/throw/return 等语句后被强制结束,插入 EOS 处理。

  return
  [a, b, c]

函数返回体 return 语句后没有使用分号,根据规则 return 语句后被结束,故编译器处理时会按以下代码处理:

  return;
  [a, b, c];

自增自减符号

在下句起始位置使用自增自减符号时,上句末尾会插入 EOS 处理。其他计算符号不会触发这一规则。

  a
  ++c

根据规则,编译器处理时会按以下代码处理:

  a;
  ++c;

代码块末句

在代码块中的最后一句语句,将会在尾部自动按插入 EOS 处理。

function() { console.log(a) }

这一句等价于

function() { console.log(a); }

No ASI 规则

在实际开发过程中,有一些开发者习惯使用无分号开发风格,这也是被语言所支持的。但在使用无分号风格前需要特别注意以下内容:

使用 .,/[(+-*% 等符号作为一行代码的起始时,需要前置分号以规避 ASI 机制自动处理造成的错误情形。

  const a = b + c
  (d + e).print()

如同上例,在不使用分号的情况下,会被处理成具有歧义的语句,其中 c 连同下行语句一起被识别为函数的调用:

  const a = b + c(d + e).print();

同理,计算符号会被连同上句结尾识别为计算式,正则表达式会被识别为除法计算,方括号会被别为数组下标,实点会被识别为上句结尾的属性或方法。

编程风格

ASI 是 JavaScript 提供的一项便利机制,开发者可以根据这一机制自行选择附带分号编写或无分号编写程序代码,由此形成了不同的编程风格,如全分号风格、半分号风格和无分号风格等。与其他产生分歧的争议点一样,不论选择使用什么风格方案,都请务必注意一下几点:

  1. 参与社区项目时“入乡随俗”,即原始项目使用什么风格,就遵守什么风格。
  2. 私人项目、企业项目的维护,遵守默认原定的风格,不轻易变更。
  3. 私人或企业的新建项目,不论风格如何,一定保持一致。

一般情况下建议使用 eslint 等工具进行必要的风格检查,在一个项目或一个团队中尽量保持一个风格。