クイズ: 高度なJSエラーマスター
例外は本当に例外的ですか?
JavaScript のエラー、全部把握してると思う?
- エラーハンドリングの腕前を試そう! 💥
- ログインやサインアップは不要です。 ✨
- 選択式問題です。 🤖 … 普通の try‑catch 問題とは違います!
JSON.stringify(error) は何を返す?
const error = new Error('Oops');console.log(JSON.stringify(error));Error オブジェクトは列挙できないプロパティ(message、name、stack)を持つため、JSON.stringify() は {} を返します。これは API 応答でエラーを送る際の典型的な落とし穴です。JSON.stringify(error, Object.getOwnPropertyNames(error)) を使うか、代わりにプレーンオブジェクトを作成してください。
これらのチェックの結果は?
class CustomError extends Error {}const err = new CustomError('test');
console.log(err instanceof CustomError);console.log(err instanceof Error);console.log(err instanceof Object);すべてのチェックは true を返します。CustomError は Error を継承し、Error は Object を継承しています。instanceof 演算子はプロトタイプチェーン全体を確認するので、CustomError のインスタンスは Error と Object のインスタンスでもあります。
iframe 間で instanceof Error はどうなる?
// In iframe:const iframeError = new Error('test');// In parent window:console.log(iframeError instanceof Error);instanceof は異なる実行コンテキスト(iframe や worker)間では false を返すことがあります。各コンテキストは独自の Error コンストラクタを持っているためです。コンテキストを超えて確実にエラーを判定したい場合は Object.prototype.toString.call(obj) === '[object Error]' を使いましょう。
文字列をthrowしたらどうなる?
try { throw "Oops!";} catch (e) { console.log(e instanceof Error); console.log(typeof e);}JavaScriptでは任意の値をthrowできる。ここでは e instanceof Error は false で、typeof e は "string" になる。これにより、捕捉した例外がすべてErrorオブジェクトであると想定したエラーハンドリングコードが壊れる可能性がある。デバッグしやすくするため、常にErrorインスタンスをthrowしよう。
err.name の値は何ですか?
class CustomError extends Error { constructor(message) { super(message); this.name = this.constructor.name; }}const err = new CustomError('test');console.log(err.name);err.name は "CustomError" です。なぜなら this.constructor.name がクラス名を返すからです。this.name = this.constructor.name を設定するのは、カスタムエラークラスがスタックトレースやエラーメッセージで正しい名前を表示するようにする一般的なパターンです。
wrapper.cause.message は何を返す?
const original = new Error('Original error');const wrapper = new Error('Wrapper', { cause: original });console.log(wrapper.cause.message);Error.cause(ES2022)はエラーをチェーンさせ、元のエラーコンテキストを保持できる。wrapper.cause は元のエラーを指すので、wrapper.cause.message は "Original error" を返す。これは下位レベルのエラーを上位コンテキストでラップする際に便利だ。
Error.captureStackTrace は何をしますか?
function createError(msg) { const err = new Error(msg); Error.captureStackTrace(err, createError); return err;}const error = createError('test');Error.captureStackTrace(V8/Node.js)は、指定した関数(createError)をスタックトレースから除外し、エラーファクトリ関数をエンドユーザーに見えなくします。これにより、ファクトリが呼び出された場所を指す、よりクリーンなスタックトレースが得られます。
エラーメッセージは何ですか?
function validate(value) { if (!value) { throw new Error( `Value ${value} is invalid` ); }}try { validate(undefined);} catch (e) { console.log(e.message);}テンプレートリテラルは補間時に undefined を文字列 "undefined" に変換します。エラーメッセージは "Value undefined is invalid" になります。よりクリーンなメッセージにするには、補間前に value ?? 'null' などのチェックを検討してください。
クライアントに何が送られる?
// Express.js routeapp.get('/api/data', (req, res) => { const error = new Error('Database failed'); res.json({ error });});res.json() は内部で JSON.stringify() を使用するため、Error オブジェクトは {} になります。クライアントは {"error":{}} を受け取ります。これを修正するには、res.json({ error: error.message }) または res.json({ error: { message: error.message, name: error.name } }) を使用します。
Promise.reject() は何を受け取れる?
Promise.reject('string').catch(e => console.log(typeof e));Promise.reject({code: 404}).catch(e => console.log(e.code));Promise.reject(42).catch(e => console.log(e));throw と同様に、Promise.reject() は任意の値(文字列、オブジェクト、数値など)を受け取れます。これにより "string"、404、42 が出力されます。Promise チェーンで捕捉した値の型は常に確認しましょう。特にサードパーティのコードが Error 以外で拒否する可能性がある場合は注意が必要です。
error.code と error.errno の信頼性はどれくらいですか?
const fs = require('fs');fs.readFile('missing.txt', (err, data) => { if (err) { console.log(err.code); // 'ENOENT' console.log(err.errno); // -2 }});code や errno のようなプロパティは環境固有(この場合は Node.js)で、標準の Error オブジェクトには含まれません。ブラウザのエラーにはこれらのプロパティはありません。常に存在を確認しましょう:if (err.code === 'ENOENT') のように、存在すると仮定しないでください。
これらのチェックは何を返す?
const fakeError = { name: 'Error', message: 'Fake error', stack: 'fake stack'};
console.log(fakeError instanceof Error);console.log(Object.prototype.toString.call( fakeError) === '[object Error]');instanceof Error はオブジェクトが Error コンストラクタで作られていないため false を返す。Object.prototype.toString.call() も false を返す(実際は '[object Object]' が返る)ので、内部の [[Class]] スロットをチェックしている。両方の手法ともこの偽エラーオブジェクトを正しく判別している。
エラーハンドリングの極意
シリアライズの落とし穴からクロスコンテキストの instanceof 失敗まで、こういった高度な概念がジュニア開発者と、すでに傷だらけのベテランを分けます。
もっと挑戦したいですか? 追加の JavaScript、アルゴリズム、その他の脳トレが揃った 全クイズコレクション をチェックしてください。