JavaScript 错误处理
错误是编程的日常——好的错误处理让程序在异常发生时优雅降级,而不是崩溃消失。
try...catch
javascript
try {
// 尝试执行的代码
const result = riskyOperation();
console.log(result);
} catch (error) {
// 出错时执行
console.error('操作失败:', error.message);
} try...catch 只捕获同步执行的错误。对于 setTimeout、Promise(未 await 时)等异步操作中的错误,try...catch 无法捕获——需要用 Promise 的 .catch() 或在 async 函数内部使用 try...catch。
throw — 主动抛出异常
javascript
function divide(a, b) {
if (b === 0) {
throw new Error('除数不能为零');
}
return a / b;
}
try {
console.log(divide(10, 0));
} catch (error) {
console.error(error.message); // "除数不能为零"
} Error 对象
javascript
const error = new Error('出错了');
error.name; // "Error"
error.message; // "出错了"
error.stack; // 调用堆栈(调试时非常有用) 内置错误类型
| 类型 | 触发场景 |
|---|---|
Error | 通用错误 |
TypeError | 类型错误:操作了不合法类型的值 |
ReferenceError | 引用错误:访问了不存在的变量 |
SyntaxError | 语法错误:代码语法有问题 |
RangeError | 范围错误:数值超出允许范围 |
javascript
try {
undefined.name; // TypeError
console.log(xyz); // ReferenceError
JSON.parse('123abc'); // SyntaxError
(42).toFixed(200); // RangeError
} catch (error) {
console.log(`${error.name}: ${error.message}`);
} 自定义错误类型
javascript
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError('用户名不能为空');
}
if (user.age < 0) {
throw new ValidationError('年龄不能为负数');
}
} finally
finally 块中的代码无论是否出错都会执行:
javascript
function processData() {
startLoading();
try {
const data = fetchAndParse();
return data;
} catch (error) {
console.error(error);
return null;
} finally {
stopLoading(); // 始终会执行——关闭 loading 动画、释放资源
}
} 全局错误捕获
javascript
// 捕获未被 try...catch 处理的错误(主要用于日志上报)
window.addEventListener('error', (event) => {
console.error('全局错误:', event.message);
// 可上报到日志服务
});
// 捕获未被处理的 Promise rejection
window.addEventListener('unhandledrejection', (event) => {
console.error('未处理的 Promise 拒绝:', event.reason);
}); 调试技巧
console 方法
javascript
console.log('普通日志');
console.warn('警告');
console.error('错误'); // 红色背景,附带堆栈
console.table([{ a: 1, b: 2 }, { a: 3, b: 4 }]); // 表格展示
const user = { name: '张三', age: 25 };
console.log('用户:', user); // 对象引用(展开看当前值)
console.dir(user); // 对象详细结构
// 计时
console.time('operation');
// ... 执行操作 ...
console.timeEnd('operation'); // "operation: 12.34ms"
// 分组
console.group('用户信息');
console.log('姓名:张三');
console.log('年龄:25');
console.groupEnd(); 使用 debugger
在代码中加入 debugger 语句,浏览器开发者工具打开时会在该行暂停执行:
javascript
function calculateTotal(items) {
let total = 0;
for (const item of items) {
debugger; // 在此暂停,可逐步检查变量
total += item.price;
}
return total;
} 浏览器断点
在 DevTools → Sources 面板中点击行号设置断点,在 Console 中直接访问断点处的变量值。这是定位复杂 bug 最高效的方法。