では 初心者向けに分かりやすく、たくさんの例題付きで throw を含む例外(エラー)の扱いを詳しく説明します。実行結果イメージや練習問題(解答付き)まで付けます。
1) まずは「例外(exception)って何?」を超かんたんに
プログラムが“いつも通り進めない状態”になったときに、処理を中断して特別な流れに飛ばす仕組みが 例外 です。throw は「ここで問題発生!例外を投げるよ(発生させるよ)」という命令、try…catch は「例外が起きたときの受け皿」です。
2) 基本:throw と try…catch
try {
throw '何か問題が起きた'; // 例外を投げる
console.log('この行は実行されません');
} catch (e) {
console.log('例外をキャッチしました:', e);
}
JavaScript実行の流れ:
throwで例外を発生 → その時点で後ろの処理は飛ばされる。- 近くの
tryに対応するcatchに処理が移り、eに投げられた値が入る。
throw に渡すものは何でもOK(文字列、数値、オブジェクト、Error オブジェクトなど)。
3) なぜ Error オブジェクトを使うのが良いのか
new Error('メッセージ') にすると、「どこでどんなエラーか」が分かりやすく、スタックトレース(どの関数で発生したかの履歴)も付くのでデバッグしやすくなります。
try {
throw new Error('この処理はできません');
} catch (err) {
console.log(err.name); // "Error"
console.log(err.message); // "この処理はできません"
console.log(err.stack); // どの行で発生したか分かる(開発で便利)
}
JavaScript4) 具体例 1:入力チェックで使うパターン(関数内部で throw)
function divide(a, b) {
if (b === 0) {
throw new Error('0で割ることはできません');
}
return a / b;
}
try {
console.log(divide(10, 2)); // 5
console.log(divide(3, 0)); // ここで例外が発生し、catchへ
} catch (e) {
console.error('エラー:', e.message);
}
JavaScriptポイント:関数内で検査して「不正」なら throw → 呼び出し元は try…catch で受け取れる。
5) 具体例 2:文字列や数値でも投げられる(でも注意)
try {
throw 'これは文字列の例外';
} catch (e) {
console.log(typeof e, e); // "string", "これは文字列の例外"
}
JavaScriptただし、型がばらばらだと扱いにくくなるので実務では Error を投げるのが標準的です。
6) try…catch…finally — 最後に必ず実行したい処理
finally ブロックは、例外が起きても起きなくても必ず実行されます(リソース解放などに便利)。
try {
console.log('処理開始');
throw new Error('問題発生');
} catch (e) {
console.log('catch:', e.message);
} finally {
console.log('必ず実行される処理(例:接続を閉じる)');
}
JavaScript出力イメージ:
処理開始
catch: 問題発生
必ず実行される処理(例:接続を閉じる)
7) 例外を再スロー(catch で処理してももう一度投げる)
時には catch で一部対応したあと、呼び出し元にまた例外を伝えたいことがあります。
function parseAndCompute(jsonStr) {
try {
const obj = JSON.parse(jsonStr);
if (!obj.value) throw new Error('valueがありません');
return obj.value * 2;
} catch (e) {
console.log('内部でログ:', e.message);
throw e; // 呼び出し元に再度投げる
}
}
try {
parseAndCompute('{"bad":1}');
} catch (e) {
console.log('呼び出し元で受けた:', e.message);
}
JavaScript8) カスタムエラークラス(より良いエラーハンドリング)
JavaScript では class を使って独自のエラー型を作れます。種類ごとに処理を分けたいときに便利。
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validate(name) {
if (!name) throw new ValidationError('名前が必要です');
}
try {
validate('');
} catch (e) {
if (e instanceof ValidationError) {
console.log('入力エラー:', e.message);
} else {
console.log('その他のエラー:', e.message);
}
}
JavaScript9) 非推奨な使い方・注意点
- 日常的な制御に例外を多用しない:例外は「特別な状況」に使うもの。普通の条件分岐は
ifで行う。 - 無意味に投げると可読性が下がる。
throwしたら必ずどこかで捕捉するか、呼び出し元で扱う設計にする(未捕捉だとプログラムが止まる)。
10) 練習問題
問題1:isAdult(age) 関数を作る。age が 20 未満なら throw new Error('未成年です') し、それ以外は "OK" を返す。呼び出して try…catch で結果をログに出す。
解答1(サンプル):
function isAdult(age) {
if (age < 20) throw new Error('未成年です');
return 'OK';
}
try {
console.log(isAdult(25)); // OK
console.log(isAdult(17)); // ここで例外
} catch (e) {
console.log('キャッチ:', e.message);
}
JavaScript問題2:safeJSONParse(str) を作って、JSON.parse で例外が出たら null を返す。成功したらオブジェクトを返す。
解答2(サンプル):
function safeJSONParse(str) {
try {
return JSON.parse(str);
} catch (e) {
return null;
}
}
console.log(safeJSONParse('{"a":1}')); // { a: 1 }
console.log(safeJSONParse('不正なJSON')); // null
JavaScript問題3(少し応用):readFile(filePath) を模した関数で、ファイルが見つからない(filePath === '' など)場合は throw new Error('ファイルが見つかりません')。呼び出し側で種類別に処理(ファイルエラーなら別メッセージ、その他は再スロー)するコードを書いてみよう。
(解答の要点:try 内で readFile を呼び、catch で e.message を判定。想定外なら throw e; で再スロー。)
まとめ(初心者が覚えるべき最重要ポイント)
throwで例外を発生させ、try…catchで受け取る。- 投げる値は何でも良いが、
new Error('説明')を使うのが実務的に便利。 finallyは「必ず実行したい処理」に使う。- 例外は便利だが乱用は禁物。入力チェックや予期しない状態で使うのが基本。
