0%

JS核心(11)-運算子、型別與文法-ASI 自動插入分號

前言

JavaScript 為什麼一下子可以有「;」號一下子有沒有「;」號呢?

ASI (Automatic Semicolon Insertion)

中文名稱為「自動分號插入」,當 JavaScript 語句沒有加上分號時,則會受到自動插入分號 (ASI) 規則影響。

在撰寫 JavaScript 中其實它是允許你不寫分號的,因為它會自動幫你插入

var a = {
  hi: 'Bob',
}
console.log(a.hi); // Bob

ASI 機制相當的方便,其中 JavaScript 的風格管理器 ESLint 中的 Standard 就是採用此方式

但是以一個工程師來講,自動這種東西其實相當的危險,舉例來講

var a = function() {
  return
  'goodmorning Bob'
}

console.log(a())

在上面程式碼我們將函式儲存在變數 a 中,並透過 console.log() 回傳顯示 goodmorning Bob,但這時候你若實際執行程式碼,應該會發現一個很奇怪的現象,不但沒有回傳 goodmorning Bob 反而是出現了 undefined

var a = function() {
  return
  'goodmorning Bob'
}

console.log(a())
// undefined

主要原因在於 ASI 所導致,因為 ASI 機制會在結尾處補上分號,因此上面程式碼實際的運行狀況如下

var a = function() {
  return; 'goodmorning Bob';
}

console.log(a())

因此才會回傳一個 undefined,因為根本沒有回傳任何東西

其中 ASI 也有另一個常見的經典錯誤,也就是立即函式

(function() {
  console.log('one')
})()

(function() {
  console.log('two')
})()
// Uncaught TypeError: (intermediate value)(...) is not a function at <anonymous>:5:1

而要解決這個錯誤的方式有兩種,一種是在立即函式結尾補上分號或者是在立即函式前面補上分號

// 第一種
(function() {
  console.log('one')
})();

(function() {
  console.log('two')
})();

// 第二種
;(function() {
  console.log('one')
})()

;(function() {
  console.log('two')
})()

基本上 ASI 比較容易出現錯誤的規則大約就是新的一行有這幾種開頭

  • ([/
  • 大部分算數運算子 (+-*%)
  • 點運算子(.)
  • 逗號(,)

但是你也必須要知道有哪些語句容易受到 ASI 影響

  • 空的陳述式
  • var 陳述式
  • 表達陳述式
  • do-while
  • continue
  • break
  • return
  • throw

詳細一點的 ASI 可以在這裡看到11.9.1Rules of Automatic Semicolon Insertion

另外這邊也有相當多範例可以參考