這個議題許多論壇、文件都有討論,在 ESlint 的規範中也可從加不加分號區分為兩大派系,至於加不加分號關鍵點則需要了解分號對於 JavaScript 的影響,開始之前可以先看看以下題目。
下方程式碼的運行預期為:
a
的值為 1請問這段程式碼運行是否正確?
var a = 1
(function() {
console.log(2)
})()
.
.
.
.
如果你嘗試運行這段程式碼,則會出現此錯誤:
Uncaught TypeError: 1 is not a function
什麼? 1 is not a function
?我們沒有打算運行數字 1,為何要說數字 1 不是函式,這種錯誤很難查找到原因,常常會在錯誤的行數上打轉。這個錯誤主要原因是上述程式碼運行時被視為同一行,概念如下:
var a = 1(function() { /* */ })()
因此立即函式的 ()
附加在 1 上,這是一個呼叫函式的語法,所以會造成 1 is not a function
的錯誤,如果要避免此錯誤就需要使用分號將其隔開:
var a = 1 // 分號隔在哪都好,隔開就對了
;(function() {
console.log(2)
})()
ASI 是 「Automatic Semicolon Insertion」的縮寫,部分的斷行程式碼運行時會自動插入分號,這個機制可以部分程式碼如果沒有加入分號也能正確運行,如以下範例:
var b = 1
++b
console.log('b', b)
此範例中,由於 ++
是屬於一元表達式,它在僅能在表達式的左方或右方置入運算元,如果沒有 ASI 的機制程式碼會轉為「var b = 1 ++ b
」 的錯誤結構。不過好在有 ASI,實際運行時他會被加入分號如下,也就不會出現如上的錯誤。
var b = 1;
++b;
console.log('b', b); // 2
再來看一個有感的片段,以下程式碼中在 return 的後方空一行後再回傳值,請問運行結果是什麼呢?
function fn() {
return
'小明'
}
console.log(fn())
這段程式碼因為 ASI 的修正,return 後方會被加上一個分號,也因為如此 return 與預期回傳的值被分了開來,所以 return 的內容為空值,最終函式也僅能接收到 undefined
的結果。
function fn() {
return;
'小明';
}
console.log(fn()); // undefined
ASI 是出自於善意,用來修正沒有加入分號的片段程式碼,但偏偏有些地方沒有發揮其用途(如本篇一開始所介紹到的立即函式),導致程式碼出現了錯誤;甚至有些程式碼不會出錯,但會讓你的程式碼運行結果不如預期。
要解決 ASI 的問題,解決方式如下:
以下整理各種「不會」自動加入分號的規則:
(
、[
、/
開始,這類型通常會直接出現「Uncaught TypeError」導致程式碼無法運行(其後方的程式碼也會無法運作)。var a = 1
var b = a
(a + b).toString()
var a = 1
[1,2,3].forEach(bar)
(function() { })()
(function() { })()
var a = 1
var b = a
/test/.test(b)
+
、-
、*
、%
作開始,這類型大多會影響運算結果,建議合併為一行撰寫。var a = 2
var b = a
+a
,
、.
作開始,這類型在實戰中很常會運用,主要是避免程式碼過長所加入的分段,並不會影響運行,多加善用可使程式碼更易於閱讀。var a = 2
var b = a
.toString()
console.log(typeof b)
var a = 1
,b = 2 // b 一樣會 var 被宣告
因此,遇到以上的標點符號前方加入分號也是解決辦法
如果需要加入分號的狀況,除了在語句的末端加入分號外,也可將分號改在「不會自動加入分號」的最前方,如 ()
本身不會自動加入分號,當有此需求時可以將 ;
加入至前方(ESLint Standard JS 規範就選擇此方法避免錯誤)。
// 執行錯誤
(function() { })()
(function() { })()
// 正確
;(function() { })()
;(function() { })()
不加入分號可以讓程式碼看起來更乾淨、精簡(對於習慣加入分號的開發者不這麼認為就是了),且在大部分正確的分段下並不會出現錯誤,僅有少部分的語句會出現執行上的錯誤(很少,大多都可避免),因此許多開發者也會選擇不加入分號,而我過去也是屬於這類型規範的愛好者。
不過在教學上,我會更傾向選擇嚴格的規範提供範例給學員,所以近幾年開發都轉為選用加入分號的規則。至於選擇何種,只要清楚運行上的限制,只要團隊允許都是好的方法。