# semi

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

一些该规则报告的问题可以通过 --fix 命令行选项 自动修复

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 字符总是结束一个语句(就像一个分号),除非满足以下条件之一:

# 规则详情

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

# 选项

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

字符串选项:

  • "always"(默认)在语句末尾需要分号
  • "never" 不允许使用分号作为语句的结尾(除了消除以 [(/+- 开头的语句的歧义)

对象选项("always" 时):

  • "omitLastInOneLineBlock": true 忽略块中的最后一个分号,其中它的大括号(以及块的内容)在同一行中

对象选项("never" 时):

  • 如果下一行以 [(/+- 开头,"beforeStatementContinuationChars": "any"(默认)忽略语句末尾的分号(或缺少分号)。
  • 如果下一行以 [(/+- 开头,则 "beforeStatementContinuationChars": "always" 需要在语句末尾使用分号。
  • 即使下一行以 [(/+- 开头,如果 "beforeStatementContinuationChars": "never" 不会造成 ASI 危险,则 "beforeStatementContinuationChars": "never" 不允许将分号作为语句的结尾。

注意: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;
}

# 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
}

# 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() }
}

# 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() {
    // ...
})()

# 何时不使用

如果您不想以任何特定方式强制使用分号(或省略),则可以关闭此规则。

Last Updated: 5/13/2023, 8:55:38 PM