JavaScript 代碼加不加分號有什麼區別

這個問題在不少文章中都討論過,在 ESlint 規範中也由於加不加分號而分爲兩大陣營,到於加不加分號,關鍵是須要了解分號對於 JavaScript 的影響,開始以前能夠先看看下面這道面試題:javascript

請問這段代碼是否可以正常運行?html

var a = 1
(function() {
  console.log(2)
})()

前端

java

程序員

面試

若是運行這段代碼,會出現下面的錯誤:segmentfault

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 自動加入分號

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 與分號的關係

再來看一個例子,下面的代碼在 return 的後面空一行後再寫要返回的值,那麼問運行結果是什麼呢?

function fn() {
  return 
  '小明'
}
console.log(fn())

這段程序代碼由於 ASI 的修正,return 的後面會被加上一個分號,因此 return 與預期返回的值被分開了,結果 return 的內容爲空值,最終的結果也只能是 undefined

function fn() {
  return;
  '小明';
}
console.log(fn()); // undefined

到底應該怎樣處理分號

原本 ASI 是出於一片好心,用來修正沒有加入分號的代碼片斷,但恰恰在有的地方並無發揮它的做用(例如本文一開始所介紹的當即函數),致使代碼出現了錯誤;甚至有些代碼不會出錯,但會使你的代碼執行結果和預期相差萬里。

解決 ASI 問題的方式以下:

  • 不管如何都要加上分號,徹底由本身決定代碼的分割
  • 牢記不會自動加入分號的規則,當不會自動插入分號時,則手動加入

不會被自動加入分號的規則

下面時各類不會自動加入分號的規則:

  1. 新行的代碼是從 ([/ 字符開始的,這類狀況通常會直接出現 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)
  1. 新行以 +-* 開始,這類狀況大多會影響運算結果,因此應該合併爲一行。
var a = 2
var b = a
+a
  1. 新行以 ,. 開始,這種用法常常會出現,主要是爲了不代碼過長而加入的分隔,這種狀況並不會影響運行,若是善用的話會使代碼更容易閱讀。
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() { })()

總結

有的人認爲不加分號可讓代碼看起來更乾淨和精簡,並且在大部分狀況下並不會出現錯誤,因此不少人在敲代碼時不會加分號。

不過我更傾向於更嚴格的規範,也許是由於我是從後端轉到前端的,習慣了。至於到底怎麼選,只要搞清楚運行上的限制,無論哪一種風格都是挺不錯的,只要你喜歡就好。

173382ede7319973.gif


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章


歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索