try...catch 仅能捕获同步代码中当前执行栈抛出的 Error 实例,如 undefined.foo()、throw new Error()、JSON.parse('{') 等;无法捕获语法错误、异步错误、Promise 拒绝、资源加载失败等。

try...catch 不能处理所有 JavaScript 异常,它只捕获同步代码中抛出的错误,对异步错误、语法错误、资源加载失败、未捕获的 Promise 拒绝等完全无效。
哪些错误 try...catch 能捕获
仅限当前执行栈中同步抛出的 Error 实例(包括 throw new Error()、throw 'msg'、运行时异常如 ReferenceError、TypeError)。
常见可捕获场景:
- 函数内直接调用不存在的方法:
undefined.foo() - 手动抛错:
throw new TypeError('invalid') - JSON 解析失败:
JSON.parse('{') // SyntaxError
示例:
立即学习“Java免费学习笔记(深入)”;
try {
JSON.parse('{');
} catch (e) {
console.log(e instanceof SyntaxError); // true
}
哪些错误 try...catch 完全捕获不到
这些错误脱离了当前 try 块的执行上下文,或发生在 JS 引擎解析/编译阶段,无法被拦截:
- 顶层语法错误(如
const后少写分号导致解析失败)——直接报SyntaxError,不进任何try - 异步回调中的错误:
setTimeout(() => { throw new Error(); }, 0) - Promise 拒绝未处理:
Promise.reject('oops')(不触发catch,但会触发unhandledrejection事件) -
fetch网络失败、图片onerror、script加载失败等资源类错误
如何补全错误捕获能力
靠单一 try...catch 必然漏掉大量真实异常,必须组合使用以下机制:
- 全局监听:
window.addEventListener('error', handler)捕获未被捕获的同步错误和资源加载错误(注意:不能捕获 Promise 错误) - Promise 错误统一处理:
window.addEventListener('unhandledrejection', e => { ... }),e.reason是拒绝原因 - 异步操作显式包裹:
async function foo() { try { await api() } catch (e) { ... } } - 第三方脚本错误兜底:在
标签加onerror属性,或用window.onerror(兼容性更好但信息较少)
注意:window.onerror 和 unhandledrejection 的回调参数结构不同,前者有 message, url, line, col, error,后者是 event.reason + event.promise。
容易忽略的关键细节
很多开发者以为加了 try...catch 就高枕无忧,实际线上最常报错的恰恰是它管不了的几类:
-
fetch成功返回 404/500 响应?这不是 JS 异常,try...catch不触发,得靠response.ok或response.status判断 - React/Vue 组件渲染时报错?默认不会冒泡到
try,需用componentDidCatch或errorCaptured钩子 - Webpack 打包后代码行号错乱?
source-map未正确上传时,error.stack几乎不可读 -
跨域脚本错误(如 CDN 资源)会被浏览器屏蔽堆栈信息,只留
"Script error."
真正健壮的错误监控,从来不是靠一个语法块,而是靠分层捕获 + 上报归因 + source map 还原 —— try...catch 只是其中最表层的一环。











