astris.design

[JS]例外処理の基本 try/catch/finally, throw

JavaScriptの例外処理は、try/catch/finally文とthrow文で記述します。例外処理の実装について、解説します(サンプルあり)。

【目次・JavaScriptの例外処理】

try/catch/finally文:例外処理

例外処理とは、スクリプト実行時にエラーが発生した際、処理の停止や、不正な処理の実行を防止するための処理のことです。
例外の多くは、外部入力や関数呼び出しで、想定外の値を受け取ったケースで発生します。

例外処理は、try/catch/finally文で実装します。
try節に、例外が発生し得る処理を記述します。例外が発生すると、それ以降のtry節の処理はスキップされ、catch節に移ります。
catch節の処理は、try節で例外が発生した場合のみ実行されます。ログ出力やリカバリのための処理を記述します。
catch節で例外を補足すると、スクリプトの処理は停止せず、以降の処理が引き続き実行されます。
例外についての情報を、Errorオブジェクトとして受け取ることができます。
finally節の処理は、例外が発生したかどうかに関わらず、必ず実行されます。リソースの解放などの後処理を記述します。
return文やbreak文で、try節を抜けた場合でも、finally節の処理は実行されます。
catch節とfinally節のいずれかを、省略することもできます(両方省略は不可)。

JavaScriptでは、例外は、コールスタックを遡ります。
例外が発生すると、処理を中断し、例外ハンドラ(catch節)に処理を移します。
例外が発生したブロックにcatch節がない場合、上位のブロックにcatch節がないか調べられます。
例外ハンドラが見つからなかった場合、スクリプトの処理は停止し、コンソールにエラー情報が通知されます。

try/catch/finally文は、オーバーヘッドの大きい処理のため、パフォーマンス低下の原因になる可能性があります。
例えば、ループ処理の中でのtry/catch/finally文の使用は避けるべきです。

構文
try {
  例外が発生し得る処理
} catch (error) {
  例外処理
} finally {
  後処理(例外の有無に関わらず実行)
}

サンプル

try.js
try {
  ++variable;
} catch (e) {
  console.log(e.name);
  //「ReferenceError」
  console.log(e.message);
  //「variable is not defined」
  console.log(e.stack);
  /*「ReferenceError: variable is not defined
    at Object.<anonymous> (C:\...\try.js:2:3)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47」*/
} finally {
  console.log('Processing completed!');
  //「Processing completed!」
}

throw文:例外を発生させる

throw文は、明示的に例外を発生させる(スローする)ことができます。
throw文によって発生した例外も、内部的に発生した例外と同様、catch節で補足することができます。
throw文は、一般的に、Errorクラスや、そのサブクラスのインスタンスをスローします。
数値(エラーコード)や文字列(エラーメッセージ)をスローすることもできますが、Errorオブジェクトを使用した方が便利です。
Node.jsやモダンなブラウザでは、Errorオブジェクトにstackプロパティを定義しています。
このプロパティで、Errorオブジェクトが生成されたタイミングでの、スタックトレースを表示することができます。

構文
throw new Error( エラーメッセージ );
throw new SyntaxError( エラーメッセージ );

サンプル
JavaScriptは、ゼロ割りでエラーとはなりません(計算結果は、Infinityとなります)。
そのため、throw文で明示的にエラーを発生指せています。

throw.js
let x = 0;
try {
  if(x === 0) {
    throw new Error('division by zero');
  }
  console.log(10 / x);
} catch (e) {
  console.log(e.name);
  //「Error」
  console.log(e.message);
  //「division by zero」
  console.log(e.stack);
  /*「Error: division by zero
    at Object.<anonymous> (C:\...\throw.js:4:11)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47」*/
} finally {
  console.log(10 / x);
  //「Infinity」
}

まとめ

JavaScriptの例外処理について、解説しました。
例外処理に関連する構文は、以下の2つになります。

  • try/catch/finally文:例外処理
  • throw文:例外を発生させる