6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2022年1月28日 JavaScript (JS Primer)エラーオブジェクト

エラーオブジェクト

throw文ではエラーオブジェクトを例外として投げることができます。 ここでは、throw文で例外として投げられるエラーオブジェクトについて見ていきます。

渡された数値が0以上ではない場合に例外を投げる関数です。 tryの中で発生させ、catchで出力しています。 Error.prototype.messageではエラーメッセージを参照することが出来ることがわかります。

function assertPositiveNumber(num) {
    if (num < 0) {
        throw new Error(`${num} is not positive.`);
    }
}

try {
    assertPositiveNumber(-1);
} catch (error) {
    console.log(error instanceof Error); // => true
    console.log(error.message); // => "-1 is not positive."

throwを行う際にnew Error をしてインスタンス化しているのはスタックトレースを得るためです。

エラーオブジェクトはそのインスタンスが作成されたファイル名や行数などのデバッグに役立つ情報を持っているのに対し、他のオブジェクトではそれらが得られません。

スタックトレースとは

  • エラーが発生したときに表示される内容で、そのエラーが発生するまでの過程(どんな処理がどの順番で呼び出されたかの流れ)を、ざっくりと表示したもの
  • そのインスタンスが作成されたファイル名や行数などのデバッグに役立つ情報を持っています。

ビルトインエラーとは、ECMAScript仕様や実行環境に組み込みで定義されているエラーオブジェクトです。

代表的なビルトインエラー

ReferenceError

存在しない変数や関数を参照した場合に発生するエラーです。

console.log(yano);

出力結果
ReferenceError: yano is not defined

SyntaxError

構文的に不正なコードを解釈しようとした場合のエラーです。基本的にSyntaxError例外は、JavaScriptを実行する前のパース段階で発生します。 そのため、実行前に発生する例外であるSyntaxErrorをtry...catch文ではcatchできません。

foo! bar!

出力結果
SyntaxError: Unexpected token '!'

以下はeval関数という渡した文字列をJavaScriptとして実行する関数を利用して パースした後にtry構文の中でSyntaxErrorを発生させている例です。 このように関数内で発生したSyntaxErrorはcatchする事ができます。

try {
    eval("foo! bar!");
} catch (error) {
    console.log(error instanceof SyntaxError); // => true
    console.log(error.name); // => "SyntaxError"
    console.log(error.message); // エラーメッセージが表示される
}

TypeError

値が期待される型ではない場合のエラーです。 「型が間違っているよ」と言っています。

以下はオブジェクトを関数として実行させています。

const fn = {};
fn();

出力結果
TypeError: fn is not a function

ビルトインエラーを投げる

ビルトインエラーのインスタンスを作成し、そのインスタンスを例外として投げることもできます。 通常のErrorオブジェクトと同じように、それぞれのビルトインエラーオブジェクトをnewしてインスタンスを作成できます。

たとえば関数の引数を文字列に限定したい場合は、次のようにTypeError例外を投げるとよいでしょう。 メッセージを確認しなくても、エラーの名前だけで型に関する例外だとすぐにわかります。

型を条件にする関数ならばTypeErrorを投げるほうがわかりやすいため、 こういった場合にビルトインエラーのインスタンスを作成すると良いです。

// 文字列を反転する関数
function reverseString(str) {
    if (typeof str !== "string") {
        throw new TypeError(`${str} is not a string`);
    }
// "100"を引数で渡した場合
    console.log(str); // => 100
    console.log(Array.from(str)); // => [ '1', '0', '0' ]
    console.log(Array.from(str).reverse()); // => [ '0', '0', '1' ]
    console.log(Array.from(str).reverse().join("")); // => 001
    return Array.from(str).reverse().join("");
}

try {
    // 数値を渡す
    reverseString(100);
} catch (error) {
    console.log(error instanceof TypeError); // => true
    console.log(error.name); // => "TypeError"
    console.log(error.message); // "100 is not a string"
}

reverseStringの引数が文字列でなければTypeErrorとなり、文字列であれば反転した文字列を返します。 Array.from(str).reverse().join("");は受け取った引数を配列にした上で並びを反転させて、要素を結合して文字列で返しています。

参考

JS primer 例外処理