Menu
日本語

JavaScriptのセミコロンとASI(自動挿入)完全ガイド

JavaScriptの構文(文・ブロック・式)の基本と、セミコロンの正しい書き方、そして自動セミコロン挿入(ASI)でハマりやすい落とし穴までまとめて解説します。

JavaScriptのコードは文の並び

JavaScriptのプログラムは、エンジンが上から順に実行していく**文(ステートメント)**の集まりです。変数宣言も1つの文、関数呼び出しも1つの文、ifforのブロックも文になります。そして、これらの文同士を区切るのがセミコロンです。

index.js
Output
Click Run to see the output here.

Three statements, three semicolons. The engine runs the first, then the second, then the third. Simple enough.

パーサーから見ると、空白やインデントにはまったく意味がありません。3つの文をセミコロンで区切って1行に詰め込んでも、動作はまったく同じです。インデントを入れるのはあくまで人間が読みやすくするためで、エンジンのためではありません。

ブロックで文をまとめる

波括弧 { }ブロック を作ります。ブロックとは、エンジンが1つのまとまりとして扱う文のグループのことです。関数の本体、if の分岐、ループの本体など、ブロックはあらゆる場所に登場します。

index.js
Output
Click Run to see the output here.

中括弧の中にある2つの console.log が、この if の本体です。閉じ括弧 } の後にセミコロンが付いていないことに注目してください。ブロックは終端記号を必要とするステートメントではないからです。if 文全体は、ブロックが閉じた時点で終わります。

} の後に必ず ; を書く言語から来た人がよくハマるポイントです。JavaScript では、単独のブロックや制御構文のブロックにセミコロンは付けません。

式とステートメントの違い

早いうちに押さえておきたい区別があります。式(expression) は値を生み出すもの、ステートメント(statement) は何かを実行するものです。

  • 2 + 3 は式です。評価されると 5 になります。
  • let x = 2 + 3; はステートメントです。変数を宣言し、式の評価結果を代入しています。
  • console.log("hi") は式です(関数呼び出しは undefined を返します)。ただし、1行として書いてセミコロンを付けると、式文(expression statement) になります。
index.js
Output
Click Run to see the output here.

普段はここまで気にする必要はありません。ただ、アロー関数や三項演算子を使うとき、あるいはJavaScriptが式を期待しているのに文を渡してしまった(逆もまた然り)ときには、この違いが効いてきます。

JavaScriptのセミコロンは必要?

率直に言うと、JavaScriptには 自動セミコロン挿入(ASI: Automatic Semicolon Insertion) という仕組みがあって、改行のほとんどの場所で抜けているセミコロンを勝手に補ってくれます。だから次のようなコードでも普通に動きます:

index.js
Output
Click Run to see the output here.

セミコロンを書かなくてもエラーにはなりません。ASI(自動セミコロン挿入)は改行ごとに「次のトークンは今の文の続きになり得るか?」をチェックし、続かないと判断したらセミコロンを補ってくれます。

このASIのおかげで、実際の現場では2つのスタイルが共存しています。

  • 常にセミコロンを書く派。 多くのコードベース、チュートリアル、スタイルガイドがこちら。
  • セミコロンを書かない派。 モダンなプロジェクトの一部(Standardスタイルや一部のReactコードベースなど)で採用。ASIに加えて、いくつかの防御的なテクニックを併用します。

どちらでも問題なく動きます。どちらが「間違い」ということもありません。本当にまずいのは一貫性がないことで、同じファイル内でスタイルが混ざるとバグを見つけにくくなります。

ASIにハマる落とし穴

ASIは99%くらいの場面で期待どおりに動いてくれます。残りの1%が曲者で、前の行の続きになり得るトークンで始まる行が問題を引き起こします。要注意なのは [(`+-/ の6つです。

たとえば次のコードを見てください。

index.js
Output
Click Run to see the output here.

普通なら xy が入れ替わりそうなものですが、実際にはそうなりません。ASI は [x, y] の前にセミコロンを入れてくれないんです。というのも、10[x, y] は「数値 10 に対するインデックスアクセス」として構文的に成立してしまうから。結果、パーサーは2行目と3行目をひとつの大きな式としてつなげて読んでしまい、実行時エラーが出たりおかしな値になったりします。

対処法としては、2行目の末尾にセミコロンを付けるのが一番手っ取り早いです:

index.js
Output
Click Run to see the output here.

あるいは、セミコロンなしスタイルで書いているなら、危険な行の 先頭 にセミコロンを付けておくという手もあります。

index.js
Output
Click Run to see the output here.

先頭の ; は、セミコロンを省略するコードベースでよく使われる防御的なテクニックです。理由を知らないと奇妙に見えますが、ちゃんと意味があります。

return の落とし穴

ASI の挙動の中でも、これだけは絶対に覚えておきたいケースがあります。サイレントバグの温床になるからです。return の直後で改行すると、ASI がそこにセミコロンを挿入してしまい、関数は undefined を返します。

index.js
Output
Click Run to see the output here.

筆者の意図はオブジェクトを返すことでした。ところがASIは行末の return を見て、そこで文を打ち切ってしまいます。結果として、オブジェクトリテラルは到達不能なコードになってしまうわけです。

直し方は簡単で、return と同じ行に値を書き始めることです:

index.js
Output
Click Run to see the output here.

throwbreakcontinueyield についても同じルールが当てはまります。キーワードとそれに続く値の間で改行しないようにしましょう。

迷わないためのシンプルなルール

JavaScript を学び始めたばかりなら、次のやり方が一番ラクです。

  1. すべての文の末尾にセミコロンを明示的に書く
  2. ifforwhile・関数宣言・クラス定義のブロックを閉じる } の後には付けない
  3. ただし、オブジェクトリテラルや、変数に代入した関数_式_のように、式として扱われる } の後には付けるconst f = function() {};
  4. フォーマッタを導入してあとは任せる(Prettier や ESLint のスタイルルールなど)。チームで決めたスタイルをフォーマッタが自動で揃えてくれるので、もう悩む必要はありません。
index.js
Output
Click Run to see the output here.

このルールは絶対的な法律ではありません。世の中のJavaScriptコードの大半で採用されている「慣習」です。特に理由がない限りは、これに従っておけば無難です。

大文字・小文字の区別と識別子

ここで、もう2つ小さなルールを押さえておきましょう。

  • JavaScriptは 大文字・小文字を区別しますuserNameusernameUserName はそれぞれ別の識別子として扱われます。
  • 識別子には英字、数字、_$ が使えますが、先頭に数字は置けません。また、classreturnfunction のような予約語も識別子には使えません。
index.js
Output
Click Run to see the output here.

$ も使えること自体は合法ですが、慣習的にライブラリ用に予約されていることが多い記号です(歴史的には jQuery が使っていましたし、今でも一部のテンプレートエンジンが使っています)。自分で選んで使うことはほとんどないでしょう。

次は: strict モード

最近の JavaScript は、こっそりと strict モード という少し厳しめのモードで動いています。これは、ゆるく許されていたいくつかの挙動を、きちんとエラーとして扱ってくれるモードです。ES モジュールやクラスの中身はデフォルトで strict モードになっていますが、実際に何が変わるのかを知っておく価値はあります。次のページで見ていきましょう。

よくある質問

JavaScriptでセミコロンは必須ですか?

結論から言うと、技術的には必須ではありません。JavaScriptにはASI(Automatic Semicolon Insertion/自動セミコロン挿入)という仕組みがあり、改行のタイミングでセミコロンを勝手に補ってくれます。ただ実務では、ほとんどのチームが明示的に書く派です。というのも、行頭が [ / ( / ` / + / - / / で始まるときなど、ASIが意図しない解釈をする罠がいくつかあるから。スタイルを決めたらPrettierのようなフォーマッタに任せてしまうのが一番ラクです。

JavaScriptのASI(自動セミコロン挿入)とは何ですか?

ASIは、改行の位置で「次のトークンを続けて読むと文として成立しない」と判断したときに、JavaScriptが自動でセミコロンを補ってくれるルールです。let x = 1 がセミコロンなしでも動くのはこのおかげ。逆に、次の行が [( のように「前の行の続きとして成立してしまう」文字で始まると、ASIは働かず2行がくっついて解釈されてしまいます。これが典型的なハマりどころです。

JavaScriptの文(ステートメント)の基本的な書き方は?

文とは「ひとつの命令」のこと。変数宣言、関数呼び出し、if ブロック、ループなどがこれにあたります。文と文の区切りはセミコロン(明示的に書くか、ASIで補われるか)で、複数の文をまとめるときは { } でブロックにします。なおJavaScriptのパーサーは空白やインデントを見ていないので、整形はあくまで人間が読みやすくするためのものだと覚えておきましょう。

Coddyでコードを学ぼう

始める