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
字符始终结束一个语句(就像分号一样),除非以下情况之一为真
- 该语句具有未关闭的括号、数组字面量或对象字面量,或者以某种不是有效结束语句的方式结束。(例如,以
.
或,
结束。) - 该行为
--
或++
(在这种情况下,它将递减/递增下一个标记。) - 它是
for()
、while()
、do
、if()
或else
,并且没有{
- 下一行以
[
、(
、+
、*
、/
、-
、,
、.
或其他只能在单个表达式中的两个标记之间找到的二元运算符开头。
规则详情
此规则强制执行分号的一致使用。
选项
此规则有两个选项,一个字符串选项和一个对象选项。
字符串选项
"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 中引入的。