JavaScript高级程序设计笔记 21

第21章 错误处理与调试

1. 错误处理

1.1 try-catch-finally

  • try:包裹可能出错的代码。
  • catch(err):捕获错误,err 是错误对象(包含 namemessagestack 等)。
  • finally:无论是否出错都会执行,常用于清理(关闭连接、清除定时器等)。
  • 如果 catch 中没有重新抛出错误,则程序不会中断。
  • finally 中的 return 会覆盖 trycatch 中的 return。
try {
  // 可能出错的代码
} catch (error) {
  console.error(error.message);
} finally {
  // 清理操作
}

1.2 throw 与错误类型

  • throw 可以抛出任意值(字符串、数字、对象、Error 实例等)。
  • 内置错误类型:
    • Error:基类型。
    • SyntaxError:语法错误。
    • ReferenceError:引用未声明变量。
    • TypeError:类型不匹配(如调用非函数)。
    • RangeError:数值超出范围(如递归耗尽栈)。
    • URIErrorencodeURI/decodeURI 参数无效。
    • EvalErroreval() 相关(很少见)。
  • 自定义错误:继承 Error 类。
class CustomError extends Error {
  constructor(message) {
    super(message);
    this.name = 'CustomError';
  }
}
throw new CustomError('自定义错误');

1.3 错误事件(全局捕获)

  • window.onerror:捕获未处理的 JavaScript 运行时错误(部分语法错误无法捕获)。
    • 参数:message, source, lineno, colno, error
    • 返回 true 可阻止默认处理(控制台报错)。
  • window.addEventListener('unhandledrejection'):捕获未处理的 Promise 拒绝。
    • event.promise, event.reason
window.onerror = (msg, url, line, col, err) => {
  console.log('全局错误:', msg, err);
  return true;
};
window.addEventListener('unhandledrejection', (event) => {
  console.error('未处理的 Promise 拒绝:', event.reason);
});

2. 调试技术

2.1 console 方法

方法 说明
console.log(msg) 普通输出
console.error(msg) 错误样式,显示堆栈
console.warn(msg) 警告样式
console.info(msg) 信息样式
console.debug(msg) 调试输出(可在控制台过滤)
console.table(data) 以表格形式输出数组/对象
console.time(label) / console.timeEnd(label) 计时
console.group(label) / groupEnd() 分组输出
console.trace() 打印调用堆栈
console.assert(condition, msg) 条件为假时输出错误
console.count(label) 计数
console.dir(obj) 显示对象的所有属性(DOM 元素显示为对象)

2.2 debugger 语句

  • 在代码中插入 debugger;,浏览器执行到该行时会自动暂停(需打开开发者工具)。
  • 可配合断点、单步调试。

2.3 浏览器开发者工具

  • 断点:行号点击设置,可设置条件断点(右键编辑)。
  • 监视:在 Sources 面板添加表达式,实时查看值变化。
  • 调用堆栈:查看函数调用顺序。
  • 作用域:查看当前闭包、局部、全局变量。
  • 异常断点:勾选 "Pause on exceptions",在抛出异常时自动暂停。
  • XHR/fetch 断点:拦截特定 URL 请求。
  • DOM 断点:元素变化(子树修改、属性修改、移除)时暂停。

2.4 性能与内存调试

  • Performance 面板:记录执行过程,分析函数耗时。
  • Memory 面板:堆快照,查找内存泄漏(闭包、未清理的 DOM 引用)。
  • Coverage 面板:查看代码覆盖率。

3. 错误处理最佳实践

  • 尽量 抛出错误对象throw new Error()),而非字符串或数字,以获取堆栈信息。
  • catch 中只处理可恢复的错误,无法恢复的应重新抛出或记录并上报。
  • 异步代码(Promise/async) 必须处理拒绝(.catchtry-catch),否则触发 unhandledrejection
  • 使用 finally 释放资源(如关闭文件、清除 loading 状态)。
  • 生产环境 不应将错误详情直接暴露给用户,应记录到后端(通过 navigator.sendBeacon 或 fetch)。
  • 开发环境 可利用 console 输出详细信息,结合断点调试。

4. 小结

  • try-catch 拦错误,finally 收尾保无漏。
  • throw 抛出自定义,Error 对象带堆栈。
  • 全局捕获 onerror + unhandledrejection。
  • 调试 console 方法多,debugger 断点不放过。
  • 浏览器工具断点调,性能内存可检查。

5. 常见面试题速查

  1. try-catch-finally 的执行顺序?
    → try 执行 → 若无错误跳过 catch → finally 始终执行。若 catch 中有 return,finally 会在 return 之前执行。

  2. 如何捕获异步代码中的错误?
    → Promise 使用 .catch();async/await 使用 try-catch;全局可监听 unhandledrejection 事件。

  3. window.onerror 能捕获所有错误吗?
    → 不能捕获 try-catch 中已处理的错误;也不能捕获资源加载错误(如图片、脚本),需用 addEventListener('error') 捕获资源错误。

  4. throw 可以抛出哪些类型的值?
    → 任意值,但推荐抛出 Error 实例或其子类,以便获得堆栈信息。

  5. debugger 语句的作用?
    → 代码执行到该行时会自动暂停(需打开开发者工具),方便调试。

  6. 如何打印调用堆栈?
    console.trace()new Error().stack

  7. console.timeconsole.timeEnd 的用途?
    → 测量代码段执行时间,自动输出到控制台。

  8. finally 中的 return 会影响 try 中的 return 吗?
    → 会,finally 中的 return 会覆盖 trycatch 中的返回值。

  9. 如何捕获未处理的 Promise 拒绝?
    → 监听 unhandledrejection 事件。

  10. 生产环境下应该如何处理错误?
    → 记录错误到服务端,向用户显示友好提示(如“操作失败,请稍后重试”)。

posted @ 2024-05-09 09:20  Li_pk  阅读(6)  评论(0)    收藏  举报