💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
持续学习,不断总结,共同进步,为了踏实,做好当下事儿~
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
💖The Start💖点点关注,收藏不迷路💖
|
📒文章目录
1. JavaScript 错误处理基础
1.1 throw
语句的作用机制
throw
是 JavaScript 中主动触发异常的语法,遵循 ECMAScript 的 Completion Record 规范。其核心特点是:
- 可抛出任意值:不仅是
Error
对象,字符串、数字甚至null
均可抛出
throw "Error occurred"; // 合法
throw 404; // 合法
throw { code: 500 }; // 合法
- 执行流中断:当
throw
执行时,当前函数调用栈会立即终止,直到被最近的try/catch
捕获
与 try/catch
的协作示例:
try {
throw new Error("Test");
} catch (err) {
console.log(err.message); // 输出 "Test"
}
1.2 Error 对象的核心属性
标准 Error
对象包含以下关键属性:
- name:标识错误类型(默认值为
"Error"
) - message:错误描述文本
- stack(非标准但通用):包含从抛出点到捕获点的调用栈
示例分析:
const err = new TypeError("Invalid type");
console.log(err.name); // "TypeError"
console.log(err.message); // "Invalid type"
console.log(err.stack); // 显示堆栈轨迹(浏览器环境)
2. throw error
的用法与特点
2.1 直接抛出非 Error 对象的值
原始值抛出的典型场景:
function validateInput(input) {
if (!input) throw "Input cannot be empty";
// 后续代码不会执行
}
行为特点:
- 抛出值会直接成为
catch
块的参数 - 无自动堆栈信息收集
- 无法通过标准错误属性访问信息
2.2 适用场景
- 快速原型开发:
// 临时调试代码
throw `DEBUG: ${variable}`;
- 轻量级验证:
function parseQuery(query) {
if (typeof query !== "string")
throw "Query must be a string";
}
- 传统系统兼容:某些旧版 API 要求返回字符串错误码
2.3 局限性
对比实验:
// 方式一:原始值抛出
try { throw "Error" } catch(e) {
console.log(e.stack); // undefined
}
// 方式二:Error 实例
try { throw new Error("Error") } catch(e) {
console.log(e.stack); // 完整调用栈
}
3. throw new Error(error)
的用法与特点
3.1 Error 构造函数的作用
构造过程解析:
function CustomError(message) {
this.name = "CustomError";
this.message = message;
Error.captureStackTrace(this, CustomError); // Node.js 特有
}
CustomError.prototype = Object.create(Error.prototype);
内置错误类型示例:
throw new SyntaxError("Unexpected token");
throw new ReferenceError("x is not defined");
3.2 结构化错误的优势
- 堆栈跟踪:
function a() { b(); }
function b() { throw new Error("Trace"); }
a();
// 堆栈会显示 a -> b -> throw 的完整路径
- 扩展属性:
const err = new Error("DB failure");
err.code = "ER_DB_CONN";
throw err;
3.3 高级用法
- 自定义错误类(ES6):
class APIError extends Error {
constructor(message, statusCode) {
super(message);
this.status = statusCode;
}
}
throw new APIError("Not Found", 404);
- 错误封装(ES2022):
try {
JSON.parse(invalidJson);
} catch (err) {
throw new Error("Parsing failed", { cause: err });
}
4. 关键区别对比
4.1 行为差异
特性 | throw error | throw new Error(error) |
---|---|---|
堆栈跟踪 | ❌ 无 | ✅ 自动生成 |
错误类型检测 | ❌ 仅能检查原始类型 | ✅ instanceof 支持 |
序列化能力 | ❌ 直接输出值 | ✅ 可定制 toJSON() |
调试工具支持 | 仅显示值 | 专用错误面板 |
4.2 性能影响
V8 引擎优化策略:
Error
构造的堆栈捕获是惰性的(首次访问stack
时生成)- 基准测试示例:
// 测试 10,000 次抛出
throw "error" ~= 2ms
throw new Error("error") ~= 15ms
5. 场景化最佳实践
5.1 何时使用 throw error
?
- 高频循环内部:
for (let i = 0; i < 1e6; i++) {
if (invalidCondition) throw `Iteration ${i} failed`;
}
- WebWorker 通信:需序列化的错误数据
5.2 何时必须使用 throw new Error
?
- 异步错误传递:
async function fetchData() {
try {
await fetch("/api");
} catch (err) {
throw new Error("Fetch failed", { cause: err });
}
}
- 错误分类处理:
try {
// ...
} catch (e) {
if (e instanceof DatabaseError) {
retryConnection();
}
}
5.3 反模式与常见陷阱
- 混淆导致的问题:
// 错误方式
const err = "Not found";
throw err; // 丢失堆栈
// 正确方式
throw new Error(err);
- Promise 未捕获:
// 危险!
new Promise(() => { throw "Uncaught" });
// 安全
new Promise(() => { throw new Error("Trackable") });
6. 现代 JavaScript 的扩展实践
6.1 ES2022 的 Error.cause
错误链分析:
try {
try {
connectToDatabase();
} catch (dbErr) {
throw new Error("Service unavailable", { cause: dbErr });
}
} catch (serviceErr) {
console.log(serviceErr.cause); // 原始数据库错误
}
6.2 TypeScript 的类型强化
类型守卫示例:
class NetworkError extends Error {
constructor(public code: number) {
super(`Network error ${code}`);
}
}
function isNetworkError(err: unknown): err is NetworkError {
return err instanceof NetworkError;
}
7. 总结
- 生产环境准则:
- 始终使用
new Error()
保证可调试性 - 自定义错误类实现业务语义化
- 始终使用
- 性能权衡:
- 仅在已证明错误抛出是性能瓶颈时考虑原始值
- 发展趋势:
- 关注 Error Cause 等新标准
- 利用 TypeScript 4.6+ 的改进错误类型推断
🔥🔥🔥道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
💖The Start💖点点关注,收藏不迷路💖
|
💖The Start💖点点关注,收藏不迷路💖
|