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
字元始終會結束語句(就像分號一樣),除非以下其中一種情況為真
- 語句具有未關閉的括號、陣列常值或物件常值,或者以其他不是結束語句的有效方式結束。(例如,以
.
或,
結尾。) - 該行為
--
或++
(在這種情況下,它將遞減/遞增下一個 Token。) - 它是
for()
、while()
、do
、if()
或else
,並且沒有{
- 下一行以
[
、(
、+
、*
、/
、-
、,
、.
或一些其他二元運算子開頭,該運算子只能在單一運算式中的兩個 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 中引入。