- ASI,全称 Automatic Semicolon Insertion(自动插入分号),是 JS 解析器在解析代码时自动添加分号的特性。
- 由于 JS 存在 ASI 机制,所以在许多情况下,即使你在本该需要分号的地方省略了分号,代码仍然能够正常运行。
- 是否在每一条语句结尾加分号,这一点根据个人喜好来决定即可。若你追求语句的简洁,且有能力区分什么情况下应该加分号,那么不加分号也是完全 ok 的。
ASI 机制
ASI,全称 Automatic Semicolon Insertion(自动插入分号),是 JS 解析器在解析代码时自动添加分号的特性。由于 JS 存在 ASI 机制,所以在许多情况下,即使你在本该需要分号的地方省略了分号,代码仍然能够正常运行。
下面是一些 JS 的 ASI (Automatic Semicolon Insertion) 示例,包括了一些常见的用例以及一些可能导致不易察觉的错误的用例:
let a = 3
console.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 编程经验,对于立即执行函数导致程序报错的问题,想必多少是遇到过的。对于这样较为常见的问题,处理过几遍自然就有经验了。总结出来的教训是,在书写立即执行函数时,如果前边还有其它代码的话,都会习惯性地在头部加上一个分号。