latest log

酩酊状態で書いたエンジニアポエムです。酩酊状態で読んでください。

JavaScript で throw "" ではなく throw new Error() を使ったほうがよい(些細な)理由

JavaScript人為的に例外を発生させるには、大きく分けると以下の2種類があります。

throw new しない書き方

throw "ソフトウェアでエラーが発生しました。サポート担当者に連絡し、この問題を報告してください。";

o_o は String 扱いで、o_o.stack も undefined になっています。

throw new する書き方

throw new Error("一般的なエラーだよ");
throw new TypeError("型がちがうよ");
throw new SyntaxError("文法おかしいよ");
throw new URIError("URIちがうよ");

他にも、RangeError, ReferenceError, MediaError, FileError, EvalError などがあります。

throw new した場合は、o_o は ErrorObject (または Error から派生しているサブクラスのオブジェクト) になり、
o_o.stack に、stack trace(どこからこの関数が呼ばれたか) が文字列で設定されています。

ブレークポイントで停止している場所までわかる?

開発者向けの情報として、stack trace をダンプしたい場合は、以下のようにするとよいのではないでしょうか。

(function() {
    try {
        throw new Error();
    } catch (o_o) {
        console.log( "CallStack:\n" + o_o.stack.split("\n").slice(2).join("\n") );
    }
})();

ちょっとした驚きなのですが、Chrome で実行すると DevTools 上でステップ実行している位置もダンプされています。

CallStack:
    at eval (eval at evaluate (unknown source), <anonymous>:8:3)
    at FrameMirror.evaluate (native)
    at Object.evaluate (<anonymous>:354:28)
    at Object.InjectedScript._evaluateOn (<anonymous>:613:39)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:573:52)
    at Object.InjectedScript.evaluateOnCallFrame (<anonymous>:656:21)
    at file://localhost/Users/(snip)/Xxx.js/lib/Xxx.js:78:9         ← ここね
    at Array.every (native)
    at _scheme (file://localhost/Users/(snip)/Xxx.js/lib/Xxx.js:62:31)

これから JavaScript を学ぶ方には、ぜひ、後者の書き方(throw new Error...)をおすすめしたいところです。

また、匿名関数を使ってしまうと、こういう時にも関数名がとれず残念な感じになりますね。

(ε・◇・)з o O ( ここまで書いておいてなんですが、Error#stack は Chrome(V8?) 独自の仕様っぽいですよ
(ε・◇・)っ ( こちらもどぞー 今時のブラウザが例外発生時にどんな情報を出しているのか調べてみたよ
(ε・◇・)з o O ( ↑ のは 2011-11-18 の記事ですよー