這個問題在很多文章中都討論過,在 ESlint 規範中也因為加不加分號而分為兩大陣營,到於加不加分號,關鍵是需要了解分號對於 JavaScript 的影響,開始之前可以先看看下面這道面試題:
請問這段程式碼是否能夠正常執行?
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() { })()
有的人認為不加分號可以讓程式碼看起來更乾淨和精簡,而且在大部分情況下並不會出現錯誤,所以很多人在敲程式碼時不會加分號。
不過我更傾向於更嚴格的規範,也許是因為我是從後端轉到前端的,習慣了。至於到底怎麼選,只要搞清楚執行上的限制,不管哪種風格都是挺不錯的,只要你喜歡就好。
更多程式設計相關知識,請存取:!!
以上就是JS程式碼中加分號和不加分號的區別的詳細內容,更多請關注TW511.COM其它相關文章!