iT邦幫忙

2021 iThome 鐵人賽

DAY 10
0
自我挑戰組

重新開始 JavaScript系列 第 10

[Day10] ASI - 自動插入分號

ASI (Automatic Semicolon Insertion)

ASI 是 JavaScript 自動插入分號的機制,當 JavaScript 語句沒有加上分號時,則會受到自動插入分號 (ASI) 規則影響

常見 ASI 規則

以下是幾種常見 ASI 規則:

範例1

當執行 continue、break、return... 語句,語句後會自動加上分號

function fn() {
    return
    '我是第一名'
}
console.log(fn()) // undefined

實際運行:

function fn() {
    return; '我是第一名';
}
console.log(fn());  // undefined

修正後:

function fn() {
    return '我是第一名';
}
console.log(fn());  // 我是第一名

範例2

當 JavaScript 語句'後一行'接到'前一行'會發生語法錯誤時,會自動加上分號

此例中雖未使用大括號包裹 if else 語句,但 ASI 有正確在每行結尾將分號加上

if (1>2) a=1
else a=2
console.log(a) // 2

實際運行:

if (1>2) a=1;
else a=2;
console.log(a); // 2

錯誤範例1

若將 else 移至與 if 同一行,因 else 並未與 if 做分隔,則會出現執行上的錯誤訊息

if (1>2) a=1 else a=2
console.log(a)

// Uncaught SyntaxError: Unexpected token 'else'

錯誤範例2

若改將 console.log 移至與 else 同一行,因 else 並未與 console.log 做分隔,所以也會出現錯誤訊息

if (1>2) a=1
else a=2 console.log(a)

// Uncaught SyntaxError: Unexpected identifier

正確範例

所以若要放置在同一行,使之正確執行,就要加入分號

if (1>2) a=1; else a=2; console.log(a);
// 2

不發生 ASI 規則,所造成的錯誤

1. 當新的一行是 ([/ 開始

範例1

新的一行是 ( 開始,不發生 ASI 規則,所以 2 個立即函式並沒有隔開,故出現錯誤

(function () {
    console.log('我是第一名')
}())

(function () {
    console.log('我是第一名')
}())

// 我是第一名
// 我是第一名
// Uncaught TypeError: (intermediate value)(...) is not a function

修正範例1

可以 在立即函式後添加分號在立即函式前添加分號 皆可修正錯誤

// 方法1

(function () {
    console.log('我是第一名')
}());
(function () {
    console.log('我是第一名')
}());

// 方法2

;(function () {
    console.log('我是第一名')
}())
;(function () {
    console.log('我是第一名')
}())

範例2

新的一行是 ( 開始,不發生 ASI 規則,第三行與第二行併在一起,解釋為 函式a 帶入參數 a+b,但 a 並不是函式所以出現錯誤訊息。

var a = 1
var b = a
(a + b).toString()
// Uncaught TypeError: a is not a function
實際運作
var a = 1;
var b = a(a + b).toString();
// Uncaught TypeError: a is not a function

範例3

此例中 /,會被解釋成運算符,而非正規表達式,所以錯誤訊息顯示 / 運算符前多了 .

var a = 1
var b = a
/test/.test(b)
// Uncaught SyntaxError: Unexpected token '.'
實際運作
var a = 1;
var b = a/test/.test(b);
// Uncaught SyntaxError: Unexpected token '.'

修正後
var a = 1;
var b = a;
/test/.test(b);

2. 新的一行以 +-*% 開始

範例

新的一行以 + 開始,不發生 ASI 規則併入上一行

var a = 2
var b = a
+a
console.log(a, b) // 2 4
實際運作
var a = 2;
var b = a+a;
console.log(a, b); // 2 4

修正後
var a = 2;
var b = a;
+a;
console.log(a, b); // 2 2

3. 新的一行以 ,. 開始

範例1

新的一行以 , 開始,不發生 ASI 規則併入上一行,所以 變數 b 轉為字串

var a = 2
var b = a
.toString()
console.log(typeof a, typeof b) // number string
實際運作
var a = 2;
var b = a.toString();
console.log(typeof a, typeof b); // number string

範例2

新的一行以 , 開始,不發生 ASI 規則併入上一行,所以 變數 b 一樣有被 var 宣告

var a = 1
,b = 2

console.log(a, b) // 1 2
實際運作
var a = 1, b = 2;
console.log(a, b); // 1 2

參考文獻

六角學院 - JavaScript 核心篇

MDN - 自動分號補全


上一篇
[Day8] JavaScript 的記憶體回收機制
下一篇
[Day11] 陳述式與表達式
系列文
重新開始 JavaScript32

尚未有邦友留言

立即登入留言