JavaScript: JavaScript エラーとデバッグ
最終更新:2026-10-13
バグのないコードを書くことは不可能です。JavaScript の作者でさえ10日間で typeof null === "object" のバグを作ってしまいました。そのため、バグの発見とエラー処理はコードの書き方を学ぶことよりも重要です。
1. エラー処理とデバッグ
| エラータイプ | 原因 | 例 |
|---|---|---|
SyntaxError |
無効な構文 | if (true { — 括弧の不一致 |
ReferenceError |
存在しない変数へのアクセス | console.log(notExist) |
TypeError |
間違った型への操作 | undefined.toString() |
RangeError |
有効範囲外の値 | new Array(-1) |
SyntaxError はコード実行前に(解析段階で)検出されます。他の3つはランタイムエラーです。
(2) try...catch...finally
try...catch を使ってランタイムエラーをキャッチし、プログラムのクラッシュを防ぎましょう。
HTML
<script>
try {
const data = JSON.parse('{bad json}');
} catch (error) {
console.log("解析失敗:", error.message);
} finally {
console.log("クリーンアップ処理");
}
</script>
catch の error オブジェクトには2つのよく使われるプロパティがあります。
error.message— エラーの説明error.name— エラータイプ名
(3) throw — エラーを手動でスローする
try...catch はランタイムエラーしかキャッチできないため、ビジネスロジックのエラーは手動でスローする必要があります。
HTML
<script>
function setAge(age) {
if (typeof age !== "number" || age < 0) {
throw new Error("年齢は正の数でなければなりません");
}
console.log("年齢を設定しました: " + age);
}
try {
setAge(-5);
} catch (e) {
console.log(e.message);
}
</script>
throw は任意の値をスローできますが、new Error() またはそのサブクラスを使用することを推奨します。スタックトレース情報が含まれるためです。
(4) カスタムエラーメッセージ
Error のサブクラスやカスタムプロパティを使って、より豊かなエラー情報を提供しましょう。
HTML
<script>
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
try {
throw new ValidationError("email", "無効なメール形式");
} catch (e) {
console.log(e.name + " [" + e.field + "]: " + e.message);
}
</script>
(5) ブラウザ DevTools(F12)
| パネル | 用途 |
|---|---|
| Console | ログの表示、コードの実行、エラーの確認 |
| Sources | ブレークポイントの設定、コードのステップ実行、変数の確認 |
| Network | ネットワークリクエスト、レスポンスステータス、読み込み時間の確認 |
| Elements | DOM とスタイルの表示・修正 |
ブレークポイントデバッグは最も強力なデバッグ手法です。Sources パネルで行番号をクリックしてブレークポイントを設定し、ページを更新するとコードがそのポイントで一時停止します。行ごとにステップ実行し、変数を確認し、コールスタックを調べましょう。
(6) console ファミリー
| メソッド | 用途 |
|---|---|
console.log() |
一般的な出力 |
console.warn() |
警告(黄色) |
console.error() |
エラー(赤色) |
console.table() |
配列/オブジェクトをテーブルで表示 |
console.time() / console.timeEnd() |
タイミング計測 |
console.group() / console.groupEnd() |
グループ化された出力 |
console.clear() |
コンソールのクリア |
console.table はオブジェクトの配列を表示する際に特に便利です。log より遥かに読みやすいです。
(7) デバッグのヒント
- 半分をコメントアウト:コードの半分をコメントアウトし、どちらの半分に問題があるかを確認して段階的に絞り込む
- console.log でまく:重要なポイントで変数の値を出力する。原始的だが効果的
- ブレークポイントデバッグ:
console.logより強力。実行を一時停止してリアルタイムで変数を変更できる - ゴムアヒルデバッグ:ゴムアヒル(または同僚)にコードを1行ずつ説明する。説明の途中でバグが見つかることも多い
(8) サンプル:JSON 解析の try/catch
▶ 試してみよう(9) サンプル:カスタムエラーとフォームバリデーション
▶ 試してみよう(10) サンプル:エラータイプクイックリファレンスと console メソッド
▶ 試してみよう❓ よくある質問
Q try...catch は SyntaxError をキャッチできますか?
A いいえ。
SyntaxError は実行が始まる前の解析段階でスローされるため、try ブロックに到達しません。ただし、ランタイムで SyntaxError が発生した場合(例:JSON.parse の失敗、new Function("bad syntax"))はキャッチできます。Q finally をいつ使うべきですか?
A エラーの有無に関わらずクリーンアップ操作を実行する必要がある場合です。ファイルを閉じる、リソースを解放する、ローディング状態を非表示にするなど。多くのシンプルなシナリオでは、
catch だけで十分です。Q throw と return の違いは何ですか?
A
return は通常のフロー用です。呼び出し元が戻り値を処理します。throw は異常なフロー用です。後続のコードをスキップし、コールスタックを遡って catch を探します。エラーには throw を、正常な結果には return を使いましょう。📖 まとめ
try/catchで実行時エラーを捕捉。finallyは常に実行、クリーンアップに最適throwでエラーを送出。new Error("メッセージ")が推奨- Errorオブジェクトは
nameとmessageプロパティを持つ。コンソールにスタックトレース表示 - 開発者ツール(F12):Sourcesパネルでブレークポイント、Watchで変数監視、ステップ実行
- コンソールメソッド:
log/warn/error/table/group/time/timeEndで効率的なデバッグ
📝 練習問題
safeDivide(a, b)関数を書きましょう。try...catch を使ってゼロ除算を処理してください(ヒント:JS でゼロ除算してもスローされないため、自分でチェックしてスローする必要があります)。結果またはエラーメッセージを返してください。safeJSONParse(str)関数を書きましょう。JSON 文字列を解析してください。失敗時は{ success: false, error: <エラーメッセージ> }を、成功時は{ success: true, data: <解析結果> }を返してください。retry(fn, times)関数を書きましょう。fnを実行し、スローされた場合は最大times回再試行してください。すべての試行が失敗した場合は最後のエラーをスローしてください。try...catch で実装してください。