例外をキャッチした時に例外の種類に応じて処理を分ける

例外がスローされる原因となるエラーにはいくつかの種類があります。 try...catch 文を使った例外処理で複数の種類の例外が発生する可能性がある場合は、スローされた例外の種類ごとに複数の catch を記述して実行する処理を分けることが可能です。ここでは try...catch 文で例外をキャッチした時に例外の種類に応じて処理を分ける方法について解説します。

(Last modified: )

例外が発生するエラーの種類

例外が発生するエラーの種類として次の 8 種類がグローバルオブジェクトとして定義されています。

Error           一般的なエラー
EvalError       eval 関数に関するエラー
InternalError   JavaScriptの内部エラー
RangeError      数値が有効範囲を超えた場合のエラー
ReferenceError  不正な参照を行った場合のエラー
SyntaxError     JavaScriptの構文エラー
TypeError       変数や引数の型が適切ではない場合のエラー
URIError        encodeURIまたはdecodeURIに関するエラー

※ ただし SyntaxError は実行時にエラーとなるのではなく実行前の時点でエラーとなるため、明示的に SyntaxError オブジェクトを作成してスローしない限りは、構文ミスが理由で実行時に例外をスローすることはないと思います。

例えば Number オブジェクトの toString メソッドでは、引数に 2 から 36 までの範囲の値しか指定できませんが、それを超える値を指定すると RangeError が発生します。

let num = 10;
console.log(num.toString(100));
>> RangeError: toString() radix argument must be between 2 and 36

また同じ処理であっても複数の種類のエラーが発生することがあります。 Number オブジェクトの toFixed メソッドでは、引数に 0 から 100 までの範囲の値しか指定できませんが、それを超える値を指定すると RangeError が発生します。また数値以外の値に対してこのメソッドを呼び出すと TypeError が発生します。また整数の数値リテラルに括弧をつけずにこのメソッドを呼び出すと SyntaxError が発生します。

let num = 3.14;
console.log(num.toFixed(1000));
>> RangeError: toFixed() digits argument must be between 0 and 100

let str = '3.14';
console.log(str.toFixed());
>> TypeError: str.toFixed is not a function

console.log(24.toFixed());
>> SyntaxError: Invalid or unexpected token

try...catch 文ではどのような種類の例外であってもスローされた例外をキャッチすることができますが、キャッチした例外の種類毎に異なる処理を行うこともできます。

例外の種類に応じて実行する処理を分ける

例外の種類が何であっても同じ処理を行いたい場合は次のように記述します。

function returnFixed(num, digits){
  try{
    return num.toFixed(digits)
  } catch(e) {
    console.error(e);
    return null;
  }
}

console.log('Start');

console.log(returnFixed(3.87654, 3));
console.log(returnFixed(3.87654, 1000));
console.log(returnFixed('3.87654', 1000));

console.log('End');

>> Start
>> 3.877
>> RangeError: toFixed() digits argument must be between 0 and 100
>> null
>> TypeError: num.toFixed is not a function
>> null
>> End

今回のサンプルでは try...catch 文が記述された外部の関数を 3 回呼び出しています。 1 回目は正常に結果が返ってきますが、 2 回目と 3 回目はそれぞれ例外が発生しています。 2 回目と 3 回目では発生した例外の種類が異なりますが同じ catch ブロック内で同じ処理を行っています。

発生した例外の種類毎に実行する処理を分けたい場合、 catch のあとの括弧の中に記述した変数 e に格納されている値を調べて条件分岐を行います。

try{
  例外が発生する可能性がある文を記述
  ・・・
} catch(e) {
  if (e instanceof RangeError){
    // RangeError が発生した場合に実行される処理
    ・・・
  } else if (e instanceof TypeError){
    // TypeError が発生した場合に実行される処理
    ・・・
  } else {
    // 上記以外の例外が発生した場合に実行される処理
    ・・・
  }
}

catch のあとの変数には例外がスローされたときに設定された値が格納されます。この値を instanceof 演算子を使って RangeError オブジェクトや TypeError オブジェクトと比較することで例外の種類を特定することができます。

それでは先ほどのサンプルを例外の種類毎に異なる処理をするように変更してみます。

function returnFixed(num, digits){
  try{
    return num.toFixed(digits)
  } catch(e) {
    if (e instanceof RangeError){
      console.error('RangeError');
      return null;
    } else if (e instanceof TypeError){
      console.error('TypeError');
      return null;
    } else {
      console.error(e);
      return null;
    }
  }
}

console.log('Start');

console.log(returnFixed(3.87654, 3));
console.log(returnFixed(3.87654, 1000));
console.log(returnFixed('3.87654', 1000));

console.log('End');

>> Start
>> 3.877
>> RangeError
>> null
>> TypeError
>> null
>> End

発生した例外の種類に応じて異なる処理を実行するように変更しました。

-- --

try...catch 文で例外をキャッチした時に例外の種類に応じて処理を分ける方法について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。