例外処理を理解する
例外は通常の処理の続きを中断し、対応するcatchへ制御を渡します。throwする値、捕捉後の流れ、finallyが戻り値へ与える影響を、小さな実行例で確かめます。
この単元で学ぶこと
- 例外発生前後の実行順を追跡する
- Errorの生成・throw・再throwを区別する
- finallyとreturnの関係を説明する
本文解説
正常な続きと例外の経路 try{console.log("A");throw new Error("bad");console.log("B");}catch(e){console.log("C");}はA、Cを表示します。throwが起こるとtry内の残りBは実行せず、対応するcatchへ移ります。catchが正常に終わればtry文の後へ進み、throwの直後の行へ戻ることはありません。
Errorを作ることと投げること const e=new Error("bad");は例外情報を持つ値を作るだけです。e.nameはError、e.messageはbad。throw e;で初めて通常の流れを中断します。TypeErrorやRangeErrorなどは問題の種類を区別するためのError系オブジェクトです。種類をnameやinstanceofで調べ、表示用のmessageと混同しないようにします。
catchが受け取るもの catch(e)のeには投げられた値が入ります。JavaScriptではthrow "stop"も可能なので、必ずError型だと決めつけてe.messageだけを読むのは一般には安全な前提ではありません。自分が投げるコードではErrorを使うと種類と説明を整理できます。eのスコープはcatchブロック内であり、外側へ自動的に残る変数ではありません。
呼出し先の失敗も捕捉する try{JSON.parse("{bad}");}catch(e){console.log(e.name);}はSyntaxErrorを表示します。これはソースコード全体の構文不正ではなく、実行中のJSON解析がthrowした例外なのでcatchできます。null.xはTypeError、未宣言の識別子の評価はReferenceErrorというように、失敗した操作で種類が異なります。
finallyで後片付けする try{console.log("A");}finally{console.log("F");}はA、Fです。例外がなくてもfinallyを通ります。catchで処理したときも通常はその後に実行されます。try/catchの処理後に資源の解放などを置く場所ですが、プロセスの強制終了や実行が永遠に戻らない場合まで必ず実行されると一般化はしません。
returnの前にもfinallyを通る function f(){try{return 1;}finally{console.log("F");}}をconsole.log(f())で呼ぶとF、1です。return値を決めてから関数を抜ける前にfinallyを実行します。finallyが正常に完了すれば元のreturnが続きます。tryから出ることと、関数の処理が完全に終了することを一段階分けて考えます。
finallyのreturnは結果を置き換える try{return 1;}finally{return 2;}なら2が返ります。tryがthrowしていてもfinallyでreturnするとその例外を隠してしまいます。後片付けだけのつもりでfinallyへreturnやthrowを追加すると、元の成功・失敗の結果が変わるため注意が必要です。例外を無視する意図がないならfinallyの仕事を後片付けに限定します。
再throwで呼出し元へ伝える 内側catchで記録した後throw e;とすれば同じ値を外側へ伝播できます。外側のcatchがあればそこで処理し、なければ未捕捉の例外になります。例外が起きたからといって、既に代入した変数や編集した配列が自動で元に戻るわけではありません。catchは処理を続けられる状態かを判断する場所です。
図解
重要ポイント
- throwの後の通常処理は飛ばされる。
- Errorの生成だけではthrowにならない。
- catchは投げられた値を受け取り、その後の制御を決める。
- finallyのreturn/throwは元の結果を置き換えうる。
間違えやすい点
- 例外をデータ変更の自動巻戻しと考えない。
- catch後に失敗箇所の次の行へ戻ると思わない。
- JSON.parseの実行時SyntaxErrorとソース全体の構文不正を区別する。
用語解説
- 例外
- 通常の処理を中断し、対応する例外処理へ制御を渡す仕組みと、その際の値。
- catch
- tryの実行中に伝わったthrowの値を受け取り処理する節。
- finally
- try/catchを抜けるときに実行する節。自身のreturnやthrowで結果を変更する場合がある。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- https://html5exam.jp/outline/objectives_lv2.html
- https://tc39.es/ecma262/2024/multipage/ordinary-and-exotic-objects-behaviours.html#sec-ordinarycallbindthis
- https://tc39.es/ecma262/2024/multipage/ecmascript-language-functions-and-classes.html#sec-class-definitions
- https://tc39.es/ecma262/2024/multipage/ecmascript-language-statements-and-declarations.html#sec-try-statement
確認問題の出題・採点や学習履歴の保存にはログインが必要です。