JavaScript | 第3章「制御フローとエラー処理」

javascrpit JavaScript
スポンサーリンク

プログラミング(特に JavaScript)では、「ただ上から下へ書いた順に処理を進めるだけ」では対応できない状況が多くあります。たとえば「ある条件のときには別の道を通る」「同じ処理を何回も繰り返す」「エラーが起きたらそれに対応する」など。これらを扱うのが 制御フロー (control flow)エラー処理 (error handling) の概念です。

以下、大事な要素を順番に見ていきます。

1. ブロック文 (Block statement)

まず、「複数の命令をまとめて扱う」ためのしくみです。波括弧 { … } で囲むことで、複数の文(ステートメント)をひとかたまりとして扱えます。

{
  statement1;
  statement2;
  // …さらに文があれば続く
}
JavaScript

例:

while (x < 10) {
  x++;
}
JavaScript

ここで { x++; } の部分がブロックです。

注意点として、古い var 宣言はこのブロックでスコープ(有効範囲)が分かれない、という性質があります。そのため、ECMAScript 6(ES6)以降では letconst を使うと、ブロック毎のスコープが正しく働きます。

2. 条件分岐 (Conditional statements)

ある条件が真 (true) か偽 (false) かによって処理を分けたいときに使う文です。主に以下のものがあります。

2.1 if … else

最も基本的な条件分岐。条件式が真ならある処理、偽なら別の処理をします。

if (condition) {
  // condition が true のとき実行
} else {
  // false のとき実行
}
JavaScript

さらに複数の条件を順番にチェックしたい場合は else if を使います。

if (cond1) {
  // …
} else if (cond2) {
  // …
} else {
  // どれにも当てはまらないとき
}
JavaScript

「条件式」は真または偽に評価されるものなら何でも使えます(比較演算子、論理演算子など)。

2.2 switch

複数の値を比較して処理を分けたいときに向いています。たとえば変数 x の値が 1, 2, 3 … のどれかで異なる処理をする、というような場面。

switch (expression) {
  case value1:
    // expression === value1 のときの処理
    break;
  case value2:
    // expression === value2 のときの処理
    break;
  default:
    // どの case にも当てはまらないとき
}
JavaScript

重要:break を忘れると、その下のケースも実行されてしまう(フォールスルー)ので注意。

3. 例外 (Exception) とその処理 — throw, try…catch…finally

プログラム実行中に「起きてはいけない事(エラー)」が発生することがあります。たとえば、未定義の変数を参照したり、外部データが不正な形式だったり。これを 例外 (exception) と言い、JavaScript ではそれを “投げる (throw)” ことで知らせ、適切な処理 (catch) をする仕組みがあります。

3.1 throw

自分でエラーを発生させたいときに使います。投げる対象には、文字列やオブジェクト、Error オブジェクトなどを使えます。

throw "エラーだ!";
throw new Error("何かがおかしい");
JavaScript

エラーを投げた場所以降の処理は中断され、例外処理がされるまで外側へ伝播します。

3.2 try…catch

try に書いた処理で例外が発生したら、catch のブロックに処理が移ります。

try {
  // 例外が発生する可能性のある処理
} catch (err) {
  // err には発生した例外(オブジェクトや値)が入る
}
JavaScript
  • try 内でエラーがなければ、通常通り進み、catch はスキップされます。
  • try 内でエラーが起きると、それ以降の try 内の処理は実行されず、すぐに catch に移ります。

最近の JavaScript では、catch の引数を省略できる構文も使えます(エラーの詳細を使わないとき用)。

3.3 finally

trycatch のあとに finally ブロックを付けると、その中の処理は “例外があってもなかろうと”、常に最後に実行されます。

try {
  // …
} catch (err) {
  // …
} finally {
  // 常に実行される後片付け処理など
}
JavaScript

たとえばファイルを開いたら必ず閉じたい、ネットワーク接続を切りたい、など「必ずやるべき処理」があれば finally に書きます。

注意:finally 内で returnthrow を使うと、trycatch の戻り値や例外を上書きしてしまうことがあります。なるべく finally 内で制御フロー (return/throw) を行うのは避けた方が無難です。

3.4 ネスト/再スロー (rethrow)

  • try…catch をネスト(内側に入れ子)して使うこともできます。内側でキャッチしなかった例外が外側に伝わることもあります。
  • catch 内で例外を再び throw する(再スロー)ことで、外側に例外を伝えることもできます。これは「この例外はこのレベルでは処理できない。上位で処理してね」という意味合いです。

4. エラーオブジェクトと主な例外タイプ

例外をキャッチするときには、どのようなエラーかを知ることが大事です。JavaScript の組み込みエラーには、次のような種類があります。

エラー名内容の一例
ReferenceError存在しない変数を参照した
TypeError型が想定と異なる操作をした
SyntaxError文法的に誤りのあるコードを評価しようとした
RangeError数値が範囲外だった
URIErrorURI 関連の関数で不正な文字列を扱った

捕まえた例外オブジェクトには、主に次のプロパティがあります:name(エラー名)、message(エラー内容の説明)など。

たとえば:

try {
  JSON.parse("不正な JSON");
} catch (err) {
  console.log(err.name);    // SyntaxError など
  console.log(err.message); // 具体的なメッセージ
}
JavaScript

5. なぜこれらが大事か・使いどころ

初心者から見て「制御フローとエラー処理を使う意味」は、次のような場面で明らかになります。

  • 条件に応じて処理を変える:ユーザーがログインしていれば A を、ログインしてなければ B をやる、など。
  • 繰り返す処理:配列の全要素に対して同じ処理をしたいとき(ループは別章ですが、“分岐”と組み合わされます)。
  • 外部入力やアプリ間連携で不確定性を扱う:サーバーから受け取るデータが必ず正しいとは限らない。例外が起きる可能性があるので、それを予め対策しておきたい。
  • 安定性の向上:エラーが起きてプログラム全体が止まるより、例外をキャッチして「代替処理をする」「エラーメッセージを出す」などできた方が良い。
タイトルとURLをコピーしました