JavaScript | 例外処理(try…catch文)

JavaScript
スポンサーリンク

JavaScriptの例外処理を初心者向けにやさしく解説

「エラーが出るのが怖い」って自然な感覚です。でも、エラーは悪者じゃない。うまく受け止めれば、あなたのコードはもっと丈夫になります。ここでは、try…catchを中心に、例題で実感できるようにかみ砕いて説明します。


エラーと例外の基本

  • エラーとは: コードが「このままじゃ続行できない」と判断したときに起きる問題のこと。たとえば存在しない関数を呼んだり、形式の違うデータを扱ったり。
  • 例外(Exception)とは: 発生したエラーを「例外」として投げ(throw)て、処理の流れを中断する仕組み。
  • ねらい: 例外処理は「止まるべきときは止める」「止めたくないときは受け止めて続ける」を選べるようにすること。

try…catchの基本形と動き

try {
  // エラーが起きるかもしれない処理
} catch (e) {
  // エラーが起きたときの代替処理
  console.error('エラー発生:', e.message);
}
JavaScript
  • try: リスクのある処理をここに入れる。
  • catch: 例外が投げられたときに実行。eはエラー情報(Errorオブジェクトなど)。
  • 効果: プログラム全体の停止を防ぎ、次の処理へ進めるかどうかを自分で決められる。

例題で理解する

1. わざとエラーを起こして受け止める

function add(a, b) {
  // BigIntとNumberを混ぜるとTypeErrorになる可能性
  return a + b;
}

try {
  const result = add(1n, 2); // ← ここで例外が起きる
  console.log('結果:', result);
} catch (e) {
  console.error('安全にキャッチ:', e.name, e.message);
  console.log('結果の代わりに既定値を返す: 0');
}
console.log('プログラムは止まらずに続行');
JavaScript
  • ポイント: 問題が起きても「既定値」を使って続行できる。ユーザー体験を壊さない。

2. JSONのパースで安全運転

function safeParse(jsonText) {
  try {
    return JSON.parse(jsonText);
  } catch (e) {
    console.error('JSONが不正です:', e.message);
    return null; // 失敗時はnullで通知
  }
}

const ok = safeParse('{"name":"Mika","age":20}');
const ng = safeParse('{"name":"Mika", age:20}'); // ← ここが不正

console.log('OK:', ok); // オブジェクト
console.log('NG:', ng); // null
JavaScript
  • ポイント: 外部やユーザー入力のデータは「壊れている前提」で守る。失敗時の戻り値を決めておくと扱いやすい。

3. finallyで後片付け

function doTask() {
  console.log('開始');
  try {
    throw new Error('処理中に問題'); // 例外発生
  } catch (e) {
    console.log('キャッチ:', e.message);
  } finally {
    console.log('後片付け'); // 例外の有無に関わらず必ず実行
  }
  console.log('終了');
}

doTask();
JavaScript
  • ポイント: finallyは「必ずやること」(片付け、接続のクローズ、ローディング表示の解除など)に使う。

4. 自分でエラーを投げる(入力チェック)

function divide(a, b) {
  if (typeof a !== 'number' || typeof b !== 'number') {
    throw new TypeError('引数は数値である必要があります');
  }
  if (b === 0) {
    throw new RangeError('0で割ることはできません');
  }
  return a / b;
}

try {
  console.log(divide(10, 0)); // ここでエラーを投げる
} catch (e) {
  console.error(`${e.name}: ${e.message}`);
}
JavaScript
  • ポイント: 「ダメな入力」は早めに拒否。バグを見つけやすくなり、後工程の謎エラーを減らせる。

実務でよくあるパターン

入力のバリデーションと既定値

function toNumber(text, defaultValue = 0) {
  const n = Number(text);
  if (Number.isNaN(n)) return defaultValue;
  return n;
}

console.log(toNumber('42'));     // 42
console.log(toNumber('abc', -1)); // -1
JavaScript
  • ポイント: 例外に頼りすぎず、事前チェックで「落ちないコード」にする考え方も大切。

fetch + try…catch(ネットワークは必ず失敗しうる)

async function fetchUser(id) {
  try {
    const res = await fetch(`https://api.example.com/users/${id}`);
    if (!res.ok) {
      throw new Error(`HTTPエラー: ${res.status}`);
    }
    return await res.json();
  } catch (e) {
    console.error('取得失敗:', e.message);
    return null; // UI側で「再試行」や「オフライン表示」に切り替え
  }
}
JavaScript
  • ポイント: ネットワークは成功が「当たり前」じゃない。失敗時のUIや再試行戦略を設計する。

例外の扱いかたの指針

  • 境界で受け止める: 外部との境界(ユーザー入力、ネットワーク、ファイル)では必ず例外対応。
  • 既定値を決める: 失敗時に返す値(null、空配列、既定オブジェクト)を統一すると、呼び出し側のコードが楽になる。
  • 早期に投げる: 想定外の状態はその場でthrowして、原因の場所をはっきりさせる。
  • ログは情報豊富に: エラー名、メッセージ、必要ならスタック(console.error(e))で後から追跡できるように。
  • finallyで整える: ローディング解除、接続解放、テンポラリの削除など「必ずやること」はfinallyへ。

小さな練習問題

  • 練習1: ユーザー入力の数値テキストを受け取り、数値ならその2倍、数値でなければ0を返す関数を作る(例外は使わずに事前チェックで)。
  • 練習2: localStorage.getItem('settings')JSON.parseで読み込む関数を作り、壊れていたら既定設定オブジェクトを返す。try…catchを使う。
  • 練習3: divide(a, b)に対して、b === 0でエラーを投げ、呼び出し側で「代替表示(’計算不可’)」に切り替える。

まとめ

  • 要点: try…catchは「止めるか、受け止めて続けるか」を選ぶためのスイッチ。finallyは「必ずやること」。throwは「その場で注意報を出す」。
  • コツ: 外部データほど壊れている前提で書く。既定値や代替表示を決めておくと、エラーは怖くなくなる。
  • 一歩: まずは自分のコードの「壊れやすい場所」を1つ見つけて、try…catchか事前チェックを入れてみよう。動きが安定して、気持ちも落ち着くはず。
タイトルとURLをコピーしました