JavaScript | throw文

JavaScript
スポンサーリンク

JavaScriptの例外とthrow文の考え方

プログラムは「うまくいく道筋」だけでなく、「うまくいかなかったときの道筋」も用意しておくと、安心して動かせます。例外は「ここで止めたい」「この条件はダメ」と知らせる仕組みです。throwはその「知らせ」を自分で出す合図、try...catchはその「知らせ」を受け止めて安全に処理を続けるための枠組みです。


例外の基本とthrow文

  • 例外とは:
    「通常の流れを中断して、特別な処理へジャンプする」仕組み。バグだけでなく、想定内の「ダメな状態」(未入力、範囲外、接続失敗など)も例外にできます。
  • throwの役割:
    その場で例外を発生させ、以降の処理を止めて、いちばん近いcatchへ渡します。
  • 基本の書き方:
throw 値;          // 文字列でもOKだが…
throw new Error('メッセージ'); // これが定番(おすすめ)
JavaScript

文字列よりErrorオブジェクトを使うと、エラーメッセージや種類、スタック情報が扱いやすくなります。


try…catchとfinallyの使い方

  • 構造:
try {
  // 普通の処理(ここでthrowが起きるかもしれない)
} catch (e) {
  // 例外を受け止める(eに例外情報が入る)
} finally {
  // 成功でも失敗でも最後に必ず実行(後片付け)
}
JavaScript
  • ポイント:
    • try: 失敗するかもしれない「危ない処理」を入れる場所。
    • catch: 失敗したときの「代わりの動き」。ユーザーへの案内、ログ記録など。
    • finally: ファイルを閉じる、ローディング表示を消すなどの後片付け。例外の有無に関わらず実行されます。

例題で学ぶ(初心者向け)

入力チェック:空文字は受け付けない

function greet(name) {
  try {
    if (!name || name.trim() === '') {
      throw new Error('名前を入力してください'); // ダメな状態を明確化
    }
    console.log(`こんにちは、${name}さん!`);
  } catch (e) {
    console.error('エラー:', e.message); // ユーザー向けのわかりやすい文
  } finally {
    console.log('greet()の処理を終了しました'); // 後片付けやログ
  }
}

greet('太郎');  // → こんにちは、太郎さん!
greet('   ');   // → エラー: 名前を入力してください
JavaScript
  • 狙い:
    空入力を例外にすることで、誤った状態を早めに止め、理由をはっきり伝えます。

範囲チェック:点数は0〜100だけ有効

function setScore(score) {
  try {
    if (typeof score !== 'number') {
      throw new TypeError('scoreは数値である必要があります');
    }
    if (score < 0 || score > 100) {
      throw new RangeError('scoreは0〜100の範囲で指定してください');
    }
    console.log('保存しました:', score);
  } catch (e) {
    console.error(`${e.name}: ${e.message}`); // 例外の種類も表示
  }
}

setScore(85);     // → 保存しました: 85
setScore('85');   // → TypeError: scoreは数値である必要があります
setScore(120);    // → RangeError: scoreは0〜100の範囲で指定してください
JavaScript
  • 狙い:
    型と範囲の2段階チェックErrorのサブタイプで「何がダメか」をより明確にします。

疑似API呼び出し:失敗したら安全に復帰

function fetchUser(id) {
  try {
    if (typeof id !== 'number' || id <= 0) {
      throw new Error('ユーザーIDが不正です');
    }

    // 疑似的に失敗することがある処理
    const success = Math.random() > 0.5;
    if (!success) {
      throw new Error('サーバーに接続できませんでした');
    }

    console.log('ユーザー取得成功:', { id, name: 'Hanako' });
  } catch (e) {
    console.warn('取得に失敗:', e.message);
    console.log('代替処理: ゲストユーザーを表示します');
  } finally {
    console.log('読み込み表示を終了'); // スピナーやローダーを消す
  }
}

fetchUser(1);  // 成功/失敗がランダム
fetchUser(-1); // → ユーザーIDが不正です
JavaScript
  • 狙い:
    外部要因で失敗しやすい処理は、失敗時の代替ルート(メッセージ表示・仮データ)を用意するとUXが安定。

実務で使えるコツ

  • 明確なメッセージ:
    何が原因で、何をすれば良いかが伝わる文章にする(例:「メール形式が不正。example@domainの形式で入力してください」)。
  • 早期に投げる:
    ダメな状態を見つけたら、その場でthrowして後続処理を実行させない。バグの発見が早まり、データ破壊を防げます。
  • 特定のError種類を使う:
    TypeError(型が違う)、RangeError(範囲外)、SyntaxError(文法)など、種類で原因がわかりやすくなる。
  • ユーザー向けと開発者向けを分ける:
    ユーザーにはやさしいメッセージログには詳細情報e.stackなど)を残す。
  • finallyで後片付け:
    ローディング解除、ファイル・接続のクローズなどはfinallyに置くと抜け漏れしません。

よくあるつまずき

  • throwしたのにcatchされない:
    同じ同期の呼び出しチェーン内try...catchが必要。非同期(setTimeoutやPromise)では、別の扱いになるので注意。
  • 文字列をthrowして解析しづらい:
    throw 'エラー'より、throw new Error('エラー')を推奨。namestackが使えるため、原因調査が楽です。
  • 例外を握りつぶす:
    catchで何もせず無視すると、問題が隠れて品質が落ちます。最低限ログを残すか、ユーザーに知らせる対応を。
タイトルとURLをコピーしました