Error オブジェクトの仕組み - JavaScript

JavaScript でエラーが発生すると、Error オブジェクトが生成されます。このオブジェクトにはエラーの名前やメッセージ、発生場所などの情報が含まれており、デバッグに欠かせない存在です。

Error オブジェクトの基本プロパティ

try {
  throw new Error('何か問題が発生しました');
} catch (error) {
  console.log(error.name);    // "Error"
  console.log(error.message); // "何か問題が発生しました"
  console.log(error.stack);   // スタックトレース
}
nameエラーの種類を表す文字列
messageエラーの説明文
stackエラー発生時のコールスタック(非標準だがほぼ全ブラウザ対応)

Error オブジェクトの作成

Error はコンストラクタなので、new を使ってインスタンスを作成できます。

const error1 = new Error('エラーメッセージ');
const error2 = Error('new なしでも動く'); // 非推奨

new を付けなくても動作しますが、一貫性のために new を付けるのが一般的です。

組み込みエラーの種類

JavaScript には用途別にいくつかのエラークラスが用意されています。

エラー名発生状況
TypeError型が不正なとき
ReferenceError未定義の変数を参照したとき
SyntaxError構文が間違っているとき
RangeError値が有効範囲外のとき
URIErrorURI 関連関数の引数が不正なとき

これらはすべて Error を継承しており、同じプロパティ(name, message, stack)を持ちます。

組み込みエラーの使い分け

// TypeError: 型が期待と違う
function greet(name) {
  if (typeof name !== 'string') {
    throw new TypeError('name は文字列である必要があります');
  }
  return `Hello, ${name}`;
}

// RangeError: 範囲外の値
function setAge(age) {
  if (age < 0 || age > 150) {
    throw new RangeError('age は 0〜150 の範囲で指定してください');
  }
  return age;
}

適切なエラー型を使うことで、エラーの原因が明確になります。

stack プロパティの中身

stack にはエラー発生時の関数呼び出し履歴が記録されています。

function a() { b(); }
function b() { c(); }
function c() { throw new Error('エラー発生'); }

try {
  a();
} catch (error) {
  console.log(error.stack);
}

出力されるスタックトレースは以下のような形式になります。

Error: エラー発生
    at c (script.js:3:15)
    at b (script.js:2:13)
    at a (script.js:1:13)
    at script.js:6:3

下から上へ読むと、どの関数からどの関数が呼ばれてエラーに至ったかがわかります。

Error オブジェクトの判定

catch で受け取ったものが Error オブジェクトかどうかは instanceof で判定できます。

try {
  throw 'ただの文字列';
} catch (error) {
  if (error instanceof Error) {
    console.log('Errorオブジェクトです');
  } else {
    console.log('Errorオブジェクトではありません:', error);
  }
}

throw は任意の値を投げられますが、Error オブジェクトを投げるのがベストプラクティスです。スタックトレースが取得でき、デバッグが容易になります。