版本

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. 该行是 --++(在这种情况下,它将递减/递增下一个标记。)
  3. 它是 for()while()doif()else,并且没有 {
  4. 下一行以 [(+*/-,. 或其他只能在单个表达式中的两个标记之间找到的二元运算符开头。

规则详情

此规则强制执行分号的一致使用。

选项

此规则有两个选项,一个字符串选项和一个对象选项。

字符串选项

  • "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 中引入的。

进一步阅读

资源

更改语言