版本

semi

要求或禁止使用分號而不是 ASI

🔧 可修正

此規則回報的一些問題可透過 --fix 命令列選項自動修正

此規則已在 ESLint v8.53.0 中棄用。請改用 @stylistic/eslint-plugin-js 中的對應規則

JavaScript 並不要求每個語句結尾都有分號。在許多情況下,JavaScript 引擎可以判斷某個位置應該有分號,並會自動添加。此功能稱為自動分號插入 (ASI),並且被認為是 JavaScript 中較具爭議性的功能之一。例如,以下兩行都是有效的

var name = "ESLint"
var website = "eslint.org";

在第一行中,JavaScript 引擎會自動插入分號,因此這不被視為語法錯誤。JavaScript 引擎仍然知道如何解釋該行,並且知道行尾表示語句的結束。

在關於 ASI 的爭論中,一般有兩種觀點。第一種是我們應該將 ASI 視為不存在,並始終手動包含分號。其理由是,始終包含分號比嘗試記住何時需要或不需要分號更容易,因此減少了引入錯誤的可能性。

然而,對於使用分號的人來說,ASI 機制有時可能很棘手。例如,考慮以下程式碼

return
{
    name: "ESLint"
};

這看起來像是回傳物件常值的 return 語句,但是,JavaScript 引擎會將此程式碼解釋為

return;
{
    name: "ESLint";
}

實際上,在 return 語句之後插入了分號,導致其下方的程式碼(區塊內的標記常值)無法存取。此規則和 no-unreachable 規則會保護您的程式碼免受此類情況影響。

另一方面,有些人認為,既然分號是自動插入的,它們是可選的,不需要手動插入。但是,對於不使用分號的人來說,ASI 機制也可能很棘手。例如,考慮以下程式碼

var globalCounter = { }

(function () {
    var n = 0
    globalCounter.increment = function () {
        return ++n
    }
})()

在此範例中,第一行之後不會插入分號,導致執行階段錯誤(因為空物件被呼叫為好像它是函式)。 no-unexpected-multiline 規則可以保護您的程式碼免受此類情況的影響。

儘管 ASI 允許您有更大的程式碼風格自由度,但它也可能使您的程式碼以意想不到的方式執行,無論您是否使用分號。因此,最好知道何時發生 ASI 以及何時不發生,並讓 ESLint 保護您的程式碼免受這些潛在的意外情況的影響。簡而言之,正如 Isaac Schlueter 曾經描述的那樣,\n 字元始終會結束語句(就像分號一樣),除非以下其中一種情況為真

  1. 語句具有未關閉的括號、陣列常值或物件常值,或者以其他不是結束語句的有效方式結束。(例如,以 ., 結尾。)
  2. 該行為 --++(在這種情況下,它將遞減/遞增下一個 Token。)
  3. 它是 for()while()doif()else,並且沒有 {
  4. 下一行以 [(+*/-,. 或一些其他二元運算子開頭,該運算子只能在單一運算式中的兩個 Token 之間找到。

規則詳細資訊

此規則強制使用一致的分號。

選項

此規則有兩個選項,一個字串選項和一個物件選項。

字串選項

  • "always" (預設) 要求在語句結尾使用分號
  • "never" 禁止在語句結尾使用分號(除了消除以 [(/+- 開頭的語句的歧義)

物件選項 (當 "always" 時)

  • "omitLastInOneLineBlock": true 禁止在程式碼區塊的花括號(因此區塊的內容)在同一行時,在該區塊中最後一個分號
  • "omitLastInOneLineClassBody": true 禁止在類別主體的的花括號(因此類別主體的內容)在同一行時,在類別主體中最後一個分號

物件選項 (當 "never" 時)

  • "beforeStatementContinuationChars": "any" (預設) 如果下一行以 [(/+- 開頭,則忽略語句結尾的分號 (或缺少分號)。
  • "beforeStatementContinuationChars": "always" 如果下一行以 [(/+- 開頭,則要求在語句結尾使用分號。
  • "beforeStatementContinuationChars": "never" 如果它不會造成 ASI 風險,即使下一行以 [(/+- 開頭,則禁止在語句結尾使用分號。

注意: beforeStatementContinuationChars 不適用於類別欄位,因為類別欄位不是語句。

always

使用預設 "always" 選項時,此規則的錯誤程式碼範例

在線上試驗場中開啟
/*eslint semi: ["error", "always"]*/

var name = "ESLint"

object.method = function() {
    // ...
}

class Foo {
    bar = 1
}

使用預設 "always" 選項時,此規則的正確程式碼範例

在線上試驗場中開啟
/*eslint semi: "error"*/

var name = "ESLint";

object.method = function() {
    // ...
};

class Foo {
    bar = 1;
}

omitLastInOneLineBlock

使用 "always", { "omitLastInOneLineBlock": true } 選項時,此規則的其他正確程式碼範例

在線上試驗場中開啟
/*eslint semi: ["error", "always", { "omitLastInOneLineBlock": true}] */

if (foo) { bar() }

if (foo) { bar(); baz() }

function f() { bar(); baz() }

class C {
    foo() { bar(); baz() }

    static { bar(); baz() }
}

omitLastInOneLineClassBody

使用 "always", { "omitLastInOneLineClassBody": true } 選項時,此規則的其他正確程式碼範例

在線上試驗場中開啟
/*eslint semi: ["error", "always", { "omitLastInOneLineClassBody": true}] */

export class SomeClass{
    logType(){
        console.log(this.type);
        console.log(this.anotherType);
    }
}

export class Variant1 extends SomeClass{type=1}
export class Variant2 extends SomeClass{type=2; anotherType=3}

never

使用 "never" 選項時,此規則的錯誤程式碼範例

在線上試驗場中開啟
/*eslint semi: ["error", "never"]*/

var name = "ESLint";

object.method = function() {
    // ...
};

class Foo {
    bar = 1;
}

使用 "never" 選項時,此規則的正確程式碼範例

在線上試驗場中開啟
/*eslint semi: ["error", "never"]*/

var name = "ESLint"

object.method = function() {
    // ...
}

var name = "ESLint"

;(function() {
    // ...
})()

import a from "a"
(function() {
    // ...
})()

import b from "b"
;(function() {
    // ...
})()

class Foo {
    bar = 1
}

beforeStatementContinuationChars

使用 "never", { "beforeStatementContinuationChars": "always" } 選項時,此規則的其他錯誤程式碼範例

在線上試驗場中開啟
/*eslint semi: ["error", "never", { "beforeStatementContinuationChars": "always"}] */
import a from "a"

(function() {
    // ...
})()

使用 "never", { "beforeStatementContinuationChars": "never" } 選項時,此規則的其他錯誤程式碼範例

在線上試驗場中開啟
/*eslint semi: ["error", "never", { "beforeStatementContinuationChars": "never"}] */
import a from "a"

;(function() {
    // ...
})()

何時不應使用

如果您不想以任何特定方式強制使用(或省略)分號,則可以關閉此規則。

版本

此規則在 ESLint v0.0.6 中引入。

延伸閱讀

資源

變更語言