1. ASI,全称 Automatic Semicolon Insertion(自动插入分号),是 JS 解析器在解析代码时自动添加分号的特性。
  2. 由于 JS 存在 ASI 机制,所以在许多情况下,即使你在本该需要分号的地方省略了分号,代码仍然能够正常运行。
  3. 是否在每一条语句结尾加分号,这一点根据个人喜好来决定即可。若你追求语句的简洁,且有能力区分什么情况下应该加分号,那么不加分号也是完全 ok 的。

ASI 机制

ASI,全称 Automatic Semicolon Insertion(自动插入分号),是 JS 解析器在解析代码时自动添加分号的特性。由于 JS 存在 ASI 机制,所以在许多情况下,即使你在本该需要分号的地方省略了分号,代码仍然能够正常运行。

下面是一些 JS 的 ASI (Automatic Semicolon Insertion) 示例,包括了一些常见的用例以及一些可能导致不易察觉的错误的用例:

  1. let a = 3
  2. console.log(a)
  3. // 解析为:
  4. let a = 3;
  5. console.log(a);
  1. if (true) {console.log('Hello')}
  2. (1, 2)
  3. // 解析为:
  4. if (true) {console.log('Hello');}
  5. (1, 2);
  1. let b = 5
  2. // 解析为:
  3. let b = 5;

然而,以下是一些不那么直观且可能引起问题的情况:

  1. function test() {
  2. return
  3. {
  4. value: "hello"
  5. }
  6. }
  7. console.log(test()); // 输出:undefined
  8. // test 函数,实际上被解析为:
  9. function test() {
  10. return;
  11. {
  12. value: "hello"
  13. };
  14. }
  1. let add = function(a, b) {
  2. return a + b
  3. } // 这里忘记添加分号
  4. (function() {
  5. // do something
  6. })()
  7. // 上述代码将会导致错误,因为 JS 将它解析为:
  8. let add = function(a, b) {
  9. return a + b
  10. }(function() {
  11. // do something
  12. })()
  13. // TypeError: (intermediate value)(...) is not a function

加分号 vs. 不加分号

虽然 ASI 是一项可以使你在某些情况下省略分号的功能,但是依赖它可能会导致代码的行为变得难以预测,因此,在你无法判断什么情况下应该加分号时,建议始终显式地在语句结束时添加分号。

如果你习惯不使用分号,那么你需要更好地理解 JS 的自动分号插入(ASI)机制,避免出现某些罕见的由于 ASI 导致的问题。

是否在每一条语句结尾加分号,这一点根据个人喜好来决定即可。若你追求语句的简洁,且有能力区分什么情况下应该加分号,那么不加分号也是完全 ok 的。

个人习惯不加分号

对于 js 语句的结尾是否加分号,个人的习惯是能不加就不加,如果运行出现了报错,再根据错误信息,加上必要的分号。

对于简单的场景,比如 return 语句后边,如果换行不加分号的话,那么 ASI 机制会在 return 语句后边自动加上分号。这样的场景接触多了,自然会下意识的注意,不会轻易出现这样的低级错误。

  1. function test() {
  2. return
  3. {
  4. value: "hello"
  5. }
  6. }
  7. test(); // undefined

其次,如果你真的不小心犯了这样的错误,在 return 后边出现了换行,那么很多 ide(比如 vscode) 都会提示你,后续的代码被置暗(Dead Code),提示你后边的是无效代码(死代码)。

image.png

再者,若出现了一些不那么容易被察觉的错误,比如常见的立即执行函数和其它语句连在一起导致的运行时报错,其实可以等到程序在执行过程中抛出的提示信息来定位。

  1. let add = function(a, b) {
  2. return a + b
  3. }
  4. // error
  5. (function() {
  6. // do something
  7. })()
  8. console.log(add(1, 2))

TypeError: (intermediate value)(…) is not a function
… (从后续的信息中,你可以获取到出错的位置)

当上述程序被执行后,会抛出一个 TypeError 错误,告诉你执行的不是一个函数,然后你再根据错误提示,在必要的位置加上分号即可。(如果你无法根据错误信息定位错误,那还是老老实实每条语句加分号吧。)

  1. let add = function(a, b) {
  2. return a + b
  3. }
  4. ;(function() {
  5. // do something
  6. })()
  7. console.log(add(1, 2)) // 3

如果你有一定的 js 编程经验,对于立即执行函数导致程序报错的问题,想必多少是遇到过的。对于这样较为常见的问题,处理过几遍自然就有经验了。总结出来的教训是,在书写立即执行函数时,如果前边还有其它代码的话,都会习惯性地在头部加上一个分号。