六角學院 JS 核心筆記 (十一)【運算子、型別與文法】- ASI 自動插入分號

ASI 即 Automatic Semicolon Insertion,當程式碼沒有加上分號時,依照 ASI 的規則,自動插入分號。它會帶來一些好處,但是也會造成一些問題。

舉例

1
2
3
4
5
6
function test() {
return
"I am Jenifer.";
}

console.log(test()); // 輸出結果:undefined

原本是預期輸出結果為 I am Jenifer.,但是卻變成 undefined,為什麼???

因為 ASI 的緣故,自動在 return 的後面加上分號,變成如下:

1
2
3
4
5
6
function test() {
return;
"I am Jenifer.";
}

console.log(test()); // 輸出結果:undefined

沒有真的回傳字串,當然不會出現如我們預期的結果。

規則

根據 JavaScript: The Definitive Guide, 6th Edition, David Flanagan, O’Reilly, 2011 提到如下:

JavaScript does not treat every line break as a semicolon: it usually treats line breaks as semicolons only if it can’t parse the code without the semicolons.

JavaScript 不會將每個換行都視為分號:只有當,兩行或多行之間沒有分號,卻也無法從語法上去解析程式碼時,它才會將換行視為分號。

例如下方第一、二行之間,就是符合上述情況。但是二、三、四行之間,雖然沒有分號,但是可以從語法上去解析程式碼,因此不會將換行視為分號,他們可以被解析成 a = 3;

1
2
3
4
var a
a
=
3

但是上述規則有兩個例外。

例外一

returnbreakcontinue 語句,遇到換行,就會被插入分號。不會跟下面一行的語句一起解析。

像是我們上面提到的 return 例子。return 和下一行的 "I am Jenifer." 中間沒有分號,而且可以從語法上去解析程式碼,應該要被解析成 return "I am Jenifer.";,但是卻沒有!

1
2
return
"I am Jenifer."

例外二

++−− 運算子不會被加在句子尾端。

下方的例子中,x 和下一行的 ++ 中間沒有分號,而且可以從語法上去解析程式碼,應該要被解析成 x++;,但是卻沒有!因為 ++ 運算子不會被加在句尾,因此下方只會被解析成 x; ++y;

1
2
3
x 
++
y

「不會」加入分號的地方

  1. 下一行是 ([/ 開始 (容易出錯的地方)
  2. 下一行以 +-*% 作開始 (會影響執行結果)
  3. 下一行以 ,. 作開始 (需注意執行結果)

上述三個需要注意的地方,仔細想想都是很合理的,例如:

1
2
test
()

如果 test 是函式名稱,應該要被解析成 test();;但是如果它不是函示,就會報錯 Uncaught TypeError: test is not a function

還有一個例子是立即函式

1
2
3
4
var name = "Jenifer"
(function (){
console.log("Hello");
})()

第一、二行之間沒有分號,( 可以從語法上去解析成要呼叫函式,但是 "Jenifer" 不是函式,因此會出錯。

總而言之,就是乖乖在正確的地方加分號就好了阿~(攤手

更完整的規則內容,請參考 11.9.1Rules of Automatic Semicolon Insertion

參考資料:
六角學院:JavaScript 核心篇 - 邁向達人之路
What are the rules for JavaScript’s automatic semicolon insertion (ASI)?