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

JavaScript
スポンサーリンク

1) 例外(エラー)って何?

プログラムを実行しているとき、「想定していない問題」が起きることがあります。例:

  • undefined のプロパティを参照した
  • 数字と文字列(あるいは BigInt)を混ぜて演算した
  • JSON のパースに失敗した

こういう「問題」が起きると JavaScript は 例外を投げる(throw) → そのままだとスクリプト全体が止まります。これを防ぎ、安全に処理するのが「例外処理」です。


2) try…catch の基本(仕組みと書き方)

try {
  // 問題が起きるかもしれない処理
} catch (e) {
  // 例外が起きたときの処理(e に例外の情報が入る)
}
JavaScript

流れ:try 内を実行 → 問題が起きたら即座に catch に移る → catch が実行されプログラムは止まらない。

簡単な例(ブラウザのコンソールで試してみてください):

try {
  console.log("処理開始");
  const x = 1 + undefinedVariable; // ReferenceError が発生(変数が無い)
  console.log("ここは実行されない");
} catch (e) {
  console.error("エラーが起きたよ:", e);
}
console.log("ここは実行され続ける");
JavaScript

3) 具体例で理解する(ステップを追って)

例題 A — 数の足し算で問題が起きるパターン

関数 sum(a, b) を作るとします。a + b が普通なら問題ないけど、a8n のような BigInt の場合 TypeError が出ます。

function sum(a, b) {
  try {
    return a + b;
  } catch (e) {
    console.error("sumでエラー:", e.message);
    return null; // エラー時の安全な返り値
  }
}

console.log(sum(2, 3));   // 5
console.log(sum(2, 8n));  // null (エラーをキャッチして続行)
JavaScript

ポイント:catch でエラー内容(e.message)を見ることで原因が分かります。


4) throw(自分で例外を投げる)

状況によっては自分で例外を作って投げる(throw)ことが有効です。例えば入力値が不正なら明示的に例外にする、など。

function divide(a, b) {
  if (b === 0) {
    throw new Error("ゼロで割ろうとしました");
  }
  return a / b;
}

try {
  console.log(divide(4, 2)); // 2
  console.log(divide(4, 0)); // ここで throw -> catch に行く
} catch (e) {
  console.error("例外:", e.message); // "ゼロで割ろうとしました"
}
JavaScript

ポイントthrow できるのは Error オブジェクトだけでなく、文字列や数値でも可能(ただし Error を使うのがベター)。


5) finally(後片付けを必ず実行する)

trycatch の後に、例外の有無に関わらず必ず実行したい処理がある場合 finally を使います(例えばファイルを閉じる、ロックを外す、など)。

try {
  // 何か処理
} catch (e) {
  // エラー処理
} finally {
  // ここは常に実行される
}
JavaScript

例:

try {
  console.log("処理開始");
  // ...何か
} catch (e) {
  console.log("エラー処理");
} finally {
  console.log("終了処理(必ず実行)");
}
JavaScript

6) 非同期(Promise / async-await)での例外

try…catchasync 関数の中でも使えますが、Promise の中の非同期処理catch を使うか awaittry を組み合わせます。

// Promise の場合
fetch("https://example.com/data.json")
  .then(res => res.json())
  .catch(err => console.error("fetchで失敗:", err));

// async/await + try/catch の場合
async function loadData() {
  try {
    const res = await fetch("https://example.com/data.json");
    const data = await res.json();
    console.log(data);
  } catch (e) {
    console.error("読み込み失敗:", e);
  }
}
JavaScript

注意try…catchawait している行で発生した例外をキャッチできます。then 内で発生する例外は別途その then に紐づく catch で捕まります(扱いに注意)。


7) よくあるパターンと対策(初心者向けチェックリスト)

  • 入力チェック(型チェック)を先に行う:typeof / Array.isArray 等で防げるエラーは防ぐ。
  • ログを残す:console.error(e)e.stack を出すと原因追跡が楽。
  • 例外を投げる場合は Error を使う:new Error("message")
  • キャッチしたら「無視」しない:単に catch {} で何もしないのはバグを隠す危険あり。
  • 非同期処理は必ず catch(または try/catch)をつける。
  • エラーは呼び出し側に伝える(null を返す/throw を再度投げるなど)取り決めをコード規約として決める。

8) 練習問題(手を動かして学ぼう)※解答付き

問題1 — safeParse を作ろう

文字列 s を JSON に変換して返す関数 safeParse(s) を作ってください。

  • 正常ならオブジェクトを返す。
  • 失敗したら null を返し、エラー内容は console.error に出力する。

解答例

function safeParse(s) {
  try {
    return JSON.parse(s);
  } catch (e) {
    console.error("JSONパース失敗:", e.message);
    return null;
  }
}
JavaScript

説明JSON.parse は不正な JSON で例外を投げるため、try/catch で包む。


問題2 — getProp(obj, key)

オブジェクト objkey プロパティを返す関数。もし objnullundefined の場合は null を返す(例外が出ないようにする)。

解答例

function getProp(obj, key) {
  try {
    return obj[key];
  } catch (e) {
    // obj が null/undefined でプロパティ参照が失敗した場合
    return null;
  }
}
JavaScript

改善案if (obj == null) return null; のように事前チェックすると try/catch を使わずに済む(より良い実装)。


問題3 — divideChecked(a, b) を作る(throw を利用)

b === 0 のときは throw new Error("ZeroDivision") をし、それを呼び出し側で try/catch して扱う。

解答例

function divideChecked(a, b) {
  if (b === 0) throw new Error("ZeroDivision");
  return a / b;
}

try {
  console.log(divideChecked(10, 2)); // 5
  console.log(divideChecked(10, 0)); // ここで throw → catch 実行
} catch (e) {
  console.error("分割に失敗:", e.message);
}
JavaScript

問題4 — 非同期:fetchJson を作る(async/await を使う)

与えられた URL から fetch して JSON を返す async 関数を作ってください。通信失敗や JSON 変換失敗は null を返す。

解答例

async function fetchJson(url) {
  try {
    const res = await fetch(url);
    if (!res.ok) throw new Error("HTTP error: " + res.status);
    return await res.json();
  } catch (e) {
    console.error("fetchJson 失敗:", e.message);
    return null;
  }
}
JavaScript

問題5 — 再スロー(rethrow)の練習

エラーをログに記録した上で、呼び出し側でも扱いたいときはどうする?rethrow を行う例を示してください。

解答例

function doSomething() {
  try {
    // 何らかの処理
    throw new Error("内部エラー"); // 例として投げる
  } catch (e) {
    console.error("内部で記録:", e.message);
    throw e; // 再スローして、呼び出し側で処理できるようにする
  }
}

try {
  doSomething();
} catch (e) {
  console.log("呼び出し側で補足:", e.message);
}
JavaScript

9) まとめ(初心者がまず覚えるべきこと)

  1. 何が例外かを把握する:どの行でエラーが出そうか考える癖をつける。
  2. まずは入力チェックで予防:防げるエラーは先に防ぐ。
  3. 例外は全部キャッチしない:必要な箇所だけに try/catch を置く。
  4. 非同期は別物await の中で発生するエラーは try/catch でキャッチする。
  5. ログを残すconsole.error(e) は原因特定の強い味方。
タイトルとURLをコピーしました