私たちが普段書いているプログラムでは、何らかの原因によって処理が妨げられることがあります。エラーを起こした際に、プログラムが強制終了されてしまうと、セキュリティやUX(ユーザーエクスペリエンス)などに悪影響を与えてしまうことが考えられます。

そのため、こうした事象をあらかじめ対処するためのプログラムを書くことも大切です。
そこで今回は、JavaScriptの例外処理とエラーオブジェクトについて解説していきます。

例外処理

「例外処理」とは、プログラムが処理されている最中にエラーを起こした際に、意図的に用意していた処理を実行する手法のことです。「エラーハンドリング」や「エラー処理」とも呼ばれています。
事前に例外処理を用意しておくと、不具合が生じた場合にも瞬時に対応ができるようになります。

以下は、JavaScriptで例外処理を行うための構文です。

  • try…catch文
  • throw文

try…catch文

「try…catch文」は、ある処理に対して、例外が起こった時の処理を行うための構文です。

tryブロック内で例外が発生すると、tryブロック内にあるそれ以降の処理は実行されなくなり、代わりに、catchブロック内で例外が発生した場合の処理を実行します。
また、finallyブロックは、例外の発生の有無に関わらず、必ず最後に処理を実行します。

try {
  実行する処理
} catch(error) {
  例外発生時の処理 
} finally {
  例外の発生に関わらず必ず最後に呼び出される処理
}

catch、またはfinallyのどちらかのブロックがあれば、もう片方のブロックは省略することが可能です。

throw文

「throw文」は、エラーが起こった際に、自ら定義したオブジェクトを例外として投げるための構文です。
エラーだと認識されたオブジェクトを、エラー処理専門の場所へ届けるイメージです。

投げられるオブジェクトには、文字列、数値、ファンクションなど、プリミティブ型やオブジェクト型が該当します。

throw '文字列';
throw 123;
throw new Error('Errorオブジェクトのインスタンス');

例外として投げられたオブジェクトは、try…catch文のcatchブロックで受け取ることができるようになります。

try {
  //例外を意図的に投げる
  throw new Error('例外が発生しました')
} catch(error) {
  console.log(error.message)
}
//'例外が発生しました'

エラーオブジェクト

ここまでtry…catch文やthrow文の例外処理方法を見ていきましたが、エラーオブジェクトの概念を知っておくことも重要です。
throw文使ってあらゆるオブジェクトを投げることができますが、エラーオブジェクト(エラー専用のオブジェクト)を使って例外処理を行うことが一般的だからです。

エラーオブジェクトには、いくつかの種類と使用できるプロパティが用意されています。以下は代表的な例です。

– エラーオブジェクトの種類

  • Error
  • ReferenceError
  • SyntaxError
  • TypeError など

– エラーオブジェクトのプロパティ

  • nameプロパティ:エラーの種類を参照
  • messageプロパティ:エラーのメッセージを参照

ここでは、最も重要なErrorオブジェクトを中心に解説していきます。あわせてプロパティも使ってみましょう。

Error

「new Error」を使用して、Errorオブジェクトを生成します。上記のthrow文の例で取り上げました。

throw文では、あらゆるオブジェクトを例外として投げることができますが、実際にはこのErrorオブジェクトのインスタンスを投げる方法が推奨されています。
理由は、Errorオブジェクトのインスタンスはデバックに役立つ情報を持っており、スタックトレースが取得できるためです。

このように、エラーの種類やメッセージを読み取ることができます。

try {
  throw new Error('文字列')
} catch(error) {
  console.log(error) //Error: 文字列
  console.log(error.name) //'Error'
  console.log(error.message) //'文字列'
}

一方、「throw ‘文字列’」などのErrorオブジェクトではないオブジェクトを投げる場合は、スタックトレースを行うことができません。

try {
  throw '文字列'
} catch(error) {
  console.log(error) //'文字列'
  console.log(error.name) //undefined
  console.log(error.message) //undefined
}

上記のことから、厳密で正確なエラー処理を行う場合には、Errorオブジェクトを使う方がベターだということが分かります。

ここで補足ですが、「エラーオブジェクト」はエラーの種類全体のことを指し、「Errorオブジェクト」は、Errorという名前のエラーオブジェクトのことを指しています。

ビルドインエラー

以下は、先ほど取り上げたErrorオブジェクト以外の代表的なエラーオブジェクトです。

・ReferenceError:存在しない関数などが参照された際に起こる
・SyntaxError:プログラムの構文が誤っている際に起こる
・TypeError:値が期待される型でない際に起こる

普段プログラムを書いていく中で、このようなエラーに遭遇したこともあるのではないでしょうか。
これらは、ビルドインエラーと呼ばれており、上記で紹介したErrorオブジェクトを継承します。
そのため、これらのエラーが発生した際には、Errorオブジェクトと同じようにプロパティを使うことができます。

実際の例

例外処理とエラーオブジェクトについて学んだところで、実際にtry…catch文の中でErrorオブジェクトを使ってみましょう。

以下は、num(郵便番号)が数値でなければ例外処理を行う例です。

function myPostalcode(num) {
  if (typeof num !== 'number') {
    throw new Error('郵便番号のフォーマットが異なります')
  } else {
    return num;
  }
}

let num = 'abcdefg';  //文字列

try {
  console.log(myPostalcode(num))
} catch(error) {
  console.log(error.message);
} finally {
  console.log('処理が完了しました')
}
//'郵便番号のフォーマットが異なります'
//'処理が完了しました'

Errorオブジェクト

「let num = ‘abcdefg’」は文字列なので(数値のフォーマットとは異なる)、if文の「throw new Error」によりErrorオブジェクトが投げられます。

投げられたErrorオブジェクトはcatchブロックで受け取るため、「’郵便番号のフォーマットが異なります’」と出力されます。
その後finallyブロックに進み、「’処理が完了しました’」という出力結果を得られるということです。

反対に、「let num = 1234567」と郵便番号が数値だった場合には、tryブロックからfinallyブロックの処理が行われます。

function myPostalcode(num) {
  if (typeof num !== 'number') {
    throw new Error('郵便番号のフォーマットが異なります')
  } else {
    return num;
  }
}

let num = 1234567; //数値

try {
console.log(myPostalcode(num))
} catch(error) {
console.log(error.message);
} finally {
console.log('処理が完了しました')
}
//1234567
//'処理が完了しました'

Errorオブジェクト2

このように例外処理を用意しておくことで、あらゆるエラーに対応できるようになります。

例えば、通信が途絶えてしまった場合や、誤った情報を入力した場合などの理由から処理が完了しなかった場合に対して、そのことを画面に表示するということができるようになります。

まとめ

今回は、JavaScriptの例外処理とエラーオブジェクトについて解説しました。

JavaScriptはシングルスレッドで動いているため、一度エラーが起きてしまうとアプリケーション自体が止まってしまう恐れがあります。
そのため、エラーが起こった際にも適切に対処をし、プログラムが動き続けるようにする必要があります。

安心して利用できるプログラムを作るために、例外処理の理解も深めていきましょう。

JavaScript関連記事