まえがき
ESLint seems like the light saber of the ASI Wars these days.
— Nicholas C. Zakas (@slicknet) 2018年1月12日
JavaScript の言語仕様に ASI 利用に関する警告を追加しようという動きがあって、セミコロン スタイルに関する議論が再燃しているようです。その中で「スタイルに関わらず避けられない落とし穴はあるので Linter ツールを利用すべき」というお話もあったので、セミコロンに関する ESLint ルールをまとめました。
ASI とは Automatic Semicolon Insertion (自動セミコロン挿入) の略。改行のある場所で構文エラーが検出されたときに自動的にセミコロンを挿入して再解釈する JavaScript の言語機能のこと。
セミコロン関連ルール
- 書式に関するもの
- semi ... 文 (Statement) の末尾にセミコロンを書くか書かないかを一貫させるルールです。
- semi-spacing ... セミコロン前後の空白を一貫させるルールです。
- semi-style ... セミコロンを行末に書くか、次の文 (Statement) の行頭に書くかを一貫させるルールです。
- no-extra-semi ... 余分なセミコロンを禁止するルールです。余分なセミコロンには、空文 (EmptyStatement) と空クラスメンバ (Empty ClassElement) があります。
- バグを防ぐもの
- no-unexpected-multiline ... 意図に反して2つの文が接続された箇所を警告するルールです。セミコロンを書かないスタイルでの ASI による落とし穴を警告できます。
- no-unreachable ... 到達できない文を警告するルールです。セミコロンを常に書くスタイルでの ASI による落とし穴を警告できます。
セミコロンを常に書くスタイル
{
"rules": {
"semi": ["error", "always"],
"semi-spacing": ["error", {"after": true, "before": false}],
"semi-style": ["error", "last"],
"no-extra-semi": "error",
"no-unexpected-multiline": "error",
"no-unreachable": "error"
}
}
こちらのスタイルで注意すべきは、return
文などの一部の文が改行を許容しないことです。例えば
function f() {
return
42;
}
console.log(f()); //→ undefined
の場合、return
と 42
の間にセミコロンが自動挿入され、f()
の戻り値は undefined
になります。このとき 42;
は到達できない文になるため、no-unreachable
ルールによって警告されて気がつくことができるでしょう。
ちなみに仕様書では、このような改行が許可されない場所に
[no LineTerminator here]
というマークが付けられています。
https://www.ecma-international.org/ecma-262/8.0/#prod-ReturnStatement
セミコロンを省略するスタイル
{
"rules": {
"semi": ["error", "never", {"beforeStatementContinuationChars": "never"}],
"semi-spacing": ["error", {"after": true, "before": false}],
"semi-style": ["error", "first"],
"no-extra-semi": "error",
"no-unexpected-multiline": "error",
"no-unreachable": "error"
}
}
このスタイルで注意すべきは、文頭が特定の文字 ((
や[
など) の場合に前の文とつながってしまうことです。例えば
const a = 42
["a", "b"].forEach(x => console.log(x))
の場合、42["a", "b"]
というプロパティアクセスになってしまい、42["a", "b"].forEach
つまり new Number(42).b.forEach
は未定義なので TypeError
(いわゆるヌルポ) になります。このとき no-unexpected-multiline
ルールによって警告されるため気づくことができるでしょう。
あとがき
セミコロンを常に書くスタイルでも、省略するスタイルでも、ASI は意図しない動作の原因になります。しかし幸運にも ESLint を利用することで意図しない動作は完全に検出できます。活用しましょう!
また、スタイルを切り替えるのも上記の設定を行って eslint --fix
コマンドを利用するだけと簡単です。自分のスタイルに悩んでいる場合、eslint --fix
で自分のコードベースに適用するとどうなるのかを見てみるのも良いかもしれませんね。
以上