關於這個問題,網上已經有很多人討論過了,我先說說自己對這個問題的回答:加!(但非必須)
有些人寫代碼,懶得加分號,除非是迫不得已才勉強放一個分號上去。如果你可以保證你寫的代碼不出現任何 bug,那當然是沒有問題,但是很多 JSer 新人,對一些隱含的問題並不是特別清楚,很容易在不知不覺中寫出一堆 bug,我們先來了解下 JS 詞法語法解析的時候,哪些情況下會自動插入分號。
一、自動插入分號的規則
注:鼠標滑過文字可以看到翻譯原文
1. 程序從左到右解析,當納入下一個 token 無法匹配任何語法:
- 如該 token 跟之前的 token 之間有至少一個 LineTerminal 行終結符違反分割
- 該 token 為 `}` 符號時
2. 程序從左到右解析,當納入下一個(或幾個) token 不能產生一條合法的語句的時候,會在這個地方插入一個分號。
3. 程序從左到右解析,當納入的 token 能夠產生一條合法語句,但是這條語句是受限產生式時,在該受限 token 前面自動插入分號。
上面提到的一些內容來自 ECMAScript5.1 第七章第九節,可以戳這里,翻譯的不太通順,實在是太難翻譯了= =
二、一些不加分號會出問題的場景
場景一:
s = a + b
(x + y).doSomething()
我們期望這是這是兩條語句,結果會被解析成:
s = a + b(x + y).doSomething();
b 在這里成了一個函數了。
場景二:
x ++ y
這個 ++ 符號會給誰?答案是:
x; ++y;
這樣的代碼當然是很少遇到,但是遇到這種情況:
場景三:
return true
我們期望返回 true,結果:
return; true;
給我們返回了 undefined。
場景四:
s = function(x){return x} (1 + 2).toString()
他被解析成了
s = function(x){return x}(1 + 2).toString()
function(x){return x}(1 + 2)
這個作為一個整體,1+2 作為參數送入函數,該函數的返回值為 3,然后執行 3.toString(),這樣的問題藏的比較深,不容易被發現。
三、規避問題
有些語句是以 [
或者 (
開頭,就像上面提到的場景一和場景四,這些 token 很容易和上一條沒有加分號的語句合並到一起,如果你不太喜歡加分號,可以這樣來處理:
s = function(x){return x} ;(1 + 2).toString()
這也是為什么我們會經常看到別人的代碼中寫出這樣的函數:
;(function(){ // ... })();
在 function 的前面加了一個分號,目的就是為了防止整個函數的返回值作為參數送入上一條語句之中。
對於場景三,要特別說明一下,除了 return 之外,還有 break 和 continue 語句,break 和 continue 類似 C 語言中的 goto ,他是可以在后面添加 tag 的,如果 tag 和 這些關鍵詞之間存在 LineTerminal ,這些 tag 就會被忽略,如:
break tag
我們期望程序會調到 tag 所指向的程序段,但結果被解析成
break; tag;
四、小結
看到上面的一些列問題,相信大家心里還是有自己的答案了,如果你有信心代碼里頭不出現因為不寫分號而導致的錯誤,那分號的取舍其實是無所謂的。