- ASI,全称 Automatic Semicolon Insertion(自动插入分号),是 JS 解析器在解析代码时自动添加分号的特性。
 - 由于 JS 存在 ASI 机制,所以在许多情况下,即使你在本该需要分号的地方省略了分号,代码仍然能够正常运行。
 - 是否在每一条语句结尾加分号,这一点根据个人喜好来决定即可。若你追求语句的简洁,且有能力区分什么情况下应该加分号,那么不加分号也是完全 ok 的。
 
ASI 机制
ASI,全称 Automatic Semicolon Insertion(自动插入分号),是 JS 解析器在解析代码时自动添加分号的特性。由于 JS 存在 ASI 机制,所以在许多情况下,即使你在本该需要分号的地方省略了分号,代码仍然能够正常运行。
下面是一些 JS 的 ASI (Automatic Semicolon Insertion) 示例,包括了一些常见的用例以及一些可能导致不易察觉的错误的用例:
let a = 3console.log(a)// 解析为:let a = 3;console.log(a);
if (true) {console.log('Hello')}(1, 2)// 解析为:if (true) {console.log('Hello');}(1, 2);
let b = 5// 解析为:let b = 5;
然而,以下是一些不那么直观且可能引起问题的情况:
function test() {return{value: "hello"}}console.log(test()); // 输出:undefined// test 函数,实际上被解析为:function test() {return;{value: "hello"};}
let add = function(a, b) {return a + b} // 这里忘记添加分号(function() {// do something})()// 上述代码将会导致错误,因为 JS 将它解析为:let add = function(a, b) {return a + b}(function() {// do something})()// TypeError: (intermediate value)(...) is not a function
加分号 vs. 不加分号
虽然 ASI 是一项可以使你在某些情况下省略分号的功能,但是依赖它可能会导致代码的行为变得难以预测,因此,在你无法判断什么情况下应该加分号时,建议始终显式地在语句结束时添加分号。
如果你习惯不使用分号,那么你需要更好地理解 JS 的自动分号插入(ASI)机制,避免出现某些罕见的由于 ASI 导致的问题。
是否在每一条语句结尾加分号,这一点根据个人喜好来决定即可。若你追求语句的简洁,且有能力区分什么情况下应该加分号,那么不加分号也是完全 ok 的。
个人习惯不加分号
对于 js 语句的结尾是否加分号,个人的习惯是能不加就不加,如果运行出现了报错,再根据错误信息,加上必要的分号。
对于简单的场景,比如 return 语句后边,如果换行不加分号的话,那么 ASI 机制会在 return 语句后边自动加上分号。这样的场景接触多了,自然会下意识的注意,不会轻易出现这样的低级错误。
function test() {return{value: "hello"}}test(); // undefined
其次,如果你真的不小心犯了这样的错误,在 return 后边出现了换行,那么很多 ide(比如 vscode) 都会提示你,后续的代码被置暗(Dead Code),提示你后边的是无效代码(死代码)。

再者,若出现了一些不那么容易被察觉的错误,比如常见的立即执行函数和其它语句连在一起导致的运行时报错,其实可以等到程序在执行过程中抛出的提示信息来定位。
let add = function(a, b) {return a + b}// error(function() {// do something})()console.log(add(1, 2))
TypeError: (intermediate value)(…) is not a function
… (从后续的信息中,你可以获取到出错的位置)
当上述程序被执行后,会抛出一个 TypeError 错误,告诉你执行的不是一个函数,然后你再根据错误提示,在必要的位置加上分号即可。(如果你无法根据错误信息定位错误,那还是老老实实每条语句加分号吧。)
let add = function(a, b) {return a + b};(function() {// do something})()console.log(add(1, 2)) // 3
如果你有一定的 js 编程经验,对于立即执行函数导致程序报错的问题,想必多少是遇到过的。对于这样较为常见的问题,处理过几遍自然就有经验了。总结出来的教训是,在书写立即执行函数时,如果前边还有其它代码的话,都会习惯性地在头部加上一个分号。
