版本

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" 選項時,此規則的不正確程式碼範例

在 Playground 中開啟
/*eslint semi: ["error", "always"]*/

var name = "ESLint"

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

class Foo {
    bar = 1
}

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

在 Playground 中開啟
/*eslint semi: "error"*/

var name = "ESLint";

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

class Foo {
    bar = 1;
}

omitLastInOneLineBlock

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

在 Playground 中開啟
/*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 } 選項時,此規則的其他正確程式碼範例

在 Playground 中開啟
/*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" 選項時,此規則的不正確程式碼範例

在 Playground 中開啟
/*eslint semi: ["error", "never"]*/

var name = "ESLint";

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

class Foo {
    bar = 1;
}

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

在 Playground 中開啟
/*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" } 選項時,此規則的其他不正確程式碼範例

在 Playground 中開啟
/*eslint semi: ["error", "never", { "beforeStatementContinuationChars": "always"}] */
import a from "a"

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

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

在 Playground 中開啟
/*eslint semi: ["error", "never", { "beforeStatementContinuationChars": "never"}] */
import a from "a"

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

何時不該使用

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

版本

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

延伸閱讀

資源

變更語言