测验:高级JS错误精通
你的异常真的异常吗?
你以为你完全掌握了 JavaScript 错误处理?
- 来测测你的错误处理功底! 💥
- 无需登录或注册。 ✨
- 选择题。 🤖 … 这些可不是你常见的 try-catch 问题!
这些检查的结果是什么?
class CustomError extends Error {}const err = new CustomError('test');
console.log(err instanceof CustomError);console.log(err instanceof Error);console.log(err instanceof Object);记住 JavaScript 继承中的原型链。
三者都返回 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);不同的上下文有不同的 Error 构造函数。
instanceof 在不同执行上下文(iframe、worker)中可能返回 false,因为每个上下文都有自己的 Error 构造函数。使用 Object.prototype.toString.call(obj) === '[object Error]' 可在跨上下文时可靠检测错误类型。
err.name 的值是什么?
class CustomError extends Error { constructor(message) { super(message); this.name = this.constructor.name; }}const err = new CustomError('test');console.log(err.name);看看 this.constructor.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 是现代 JavaScript 中用于错误链的特性。
Error.cause(ES2022)允许链式错误以保留原始错误上下文。wrapper.cause 引用原始错误,因此 wrapper.cause.message 返回 "原始错误"。这对于用高层上下文包装底层错误非常有用。
Error.captureStackTrace 的作用是什么?
function createError(msg) { const err = new Error(msg); Error.captureStackTrace(err, createError); return err;}const error = createError('test');这是 V8 特有的功能,用于生成更清晰的堆栈追踪。
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 转换为字符串 "undefined"。错误信息变为 "Value undefined is invalid"。为了更清晰的消息,可以考虑在插值前使用 value ?? 'null' 或类似的检查。
什么会被发送到客户端?
// Express.js routeapp.get('/api/data', (req, res) => { const error = new Error('Database failed'); res.json({ error });});记住 Error 对象是如何被 JSON.stringify 序列化的。
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));Promise 拒绝与 throw 语句类似。
与 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 }});考虑不同的 JavaScript 环境和错误类型。
像 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 返回 false,因为该对象不是由 Error 构造函数创建的。Object.prototype.toString.call() 也返回 false(它返回 '[object Object]'),因为它检查内部 [[Class]] 槽。这两种方法都正确地将其识别为伪造的错误对象。
掌握错误处理的艺术
从序列化陷阱到跨上下文 instanceof 失败,这些高级概念将初级开发者与经验丰富的饱经摧残的专业人士区分开来。
准备好迎接更多挑战了吗?查看我们的完整测验合集,获取更多关于 JavaScript、算法等的烧脑题目!