javascript中错误如何捕获_如何处理异常呢

try-catch仅捕获同步运行时错误,无法捕获语法错误和异步错误;异步错误需用Promise.catch、await+try-catch、回调内try-catch或全局error/unhandledrejection监听;抛错应使用new Error()并补充name、stack及自定义属性。

try-catch 捕获同步错误最直接

JavaScript 中同步代码出错,try-catch 是唯一能拦截并处理的机制。它不会捕获语法错误(如 const a = ;),但能抓住运行时异常,比如 undefined.foo()JSON.parse('invalid') 或手动抛出的 throw new Error()

关键点:

  • catch 块接收一个参数(通常叫 error),它至少有 messagestack 属性
  • 不要只打印 error.message —— 丢掉调用栈就很难定位问题源头
  • 避免空 catch
    try { riskyCall(); } catch (e) {}
    这等于把错误吞掉,后续排查会非常被动
  • 可以按错误类型做分支处理:if (error instanceof TypeError) 或检查 error.name

异步错误不能靠 try-catch 直接包住

setTimeoutfetchPromise 内部抛出的错误,写在 try 块里也捕获不到——因为执行时机已脱离当前调用栈。

正确做法分场景:

  • Promises:必须用 .catch()await 配合 try-catch(注意 await 只对 Promise rejection 生效)
    try { const res = await fetch('/api'); if (!res.ok) throw new Error('HTTP error'); } catch (err) { console.error(err); }
  • async 函数外的 Promise:漏掉 .catch() 会导致 UnhandledRejection,触发 window.addEventListener('unhandledrejection')
  • setTimeout/setInterval:错误只能在回调内部 try-catch,或靠全局 window.onerror

window.onerror 和 window.addEventListener('error') 区别在哪

这两个都是捕获全局错误的兜底手段,但覆盖范围不同:

  • window.onerror:捕获 JS 运行时错误、脚本加载失败(script.src 404)、以及部分资源加载错误(需配合 crossorigin
  • window.addEventListener('error'):主要捕获资源加载错误),但**不捕获 JS 执行错误**
  • 两者都收不到 Promise rejection,得单独监听 unhandledrejection
  • 注意:它们无法获取 error.stack 的完整信息(尤其跨域脚本),所以生产环境建议搭配 try-catch 主动上报关键路径

throw new Error() 不要只写字符串

手动抛错时,throw 'something went wrong' 看似简单,但会丢失关键上下文:

  • 没有 stack,无法知道在哪一行抛出
  • 没有 name,难以分类(比如区分 ValidationErrorNetworkError
  • 推荐写法:
    throw new Error('Failed to parse user data');
    或自定义错误类:
    class ValidationError extends Error { constructor(message) { super(message); this.name = 'ValidationError'; } }
  • 如果需要附带数据(如字段名、状态码),可直接往实例上挂属性:err.field = 'email'; err.status = 400;
实际项目里最容易被忽略的是:unhandledrejection 默认静默,不报错也不提示,等用户反馈才暴露问题。上线前务必加监听并上报。