try...catch 仅捕获当前执行上下文的同步抛出错误,如 TypeError、ReferenceError、SyntaxError(JSON.parse 时)等;不捕获语法错误、异步错误、未处理 Promise 拒绝及全局错误。

JavaScript 中的 try...catch 能捕获同步代码中的运行时错误,但对异步错误、语法错误、Promise 拒绝(未处理的 reject)和全局错误无效——这是最常被误解的一点。
哪些错误能被 try...catch 捕获?
仅限当前执行上下文中的同步抛出(throw)错误,比如类型错误、引用错误、手动 throw new Error() 等。
以下情况不会被捕获:
- 顶层语法错误(如
const a = ;),直接阻断解析,try...catch根本没机会执行 -
setTimeout(() => { throw new Error('x') }, 0)—— 异步回调在新执行栈中抛错 - 未
await的 Promise 拒绝:fetch('/404').catch(...)不写.catch就会触发unhandledrejection,而非进入catch块
try...catch 必须配合 throw 或可能出错的内置操作
它本身不“检测”错误,只“拦截”已抛出的错误。常见误用是把它套在看似安全但实际不会抛错的表达式上:
立即学习“Java免费学习笔记(深入)”;
try {
const result = 2 + 2; // ✅ 不会抛错,catch 永远不会执行
} catch (e) {
console.log(e);
}
真正有用的是包裹可能失败的操作:
-
JSON.parse(str)—— 输入非法 JSON 时抛SyntaxError -
someObject.someMethod()—— 方法不存在时抛TypeError -
localStorage.setItem(key, value)—— 存储超限时抛QuotaExceededError
如何捕获异步错误?不能只靠 try...catch
对于 async/await,必须确保 await 的 Promise 被拒绝时能被 catch 捕获;而纯回调或未 await 的 Promise 需要额外处理:
-
async函数内:用try...catch包裹await fetch(...)是有效的 - 未
await的 Promise:必须显式调用.catch(),否则错误会变成unhandledrejection - 全局兜底:监听
window.addEventListener('unhandledrejection', ...)和window.addEventListener('error', ...)
示例:
async function loadData() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('加载失败:', err.message);
}
}
别忽略 finally 和错误对象细节
finally 块总会执行,适合清理资源(如关闭加载状态、释放锁),但它不接收错误参数,也不能修改错误传播行为。
错误对象通常有 message、name、stack 属性,但不同浏览器对 stack 的格式支持不一;生产环境建议用 err.toString() 或 err.name + ': ' + err.message 做基础识别。
容易被忽略的点:
-
catch参数名不是必须叫e或err,但重命名后别误用旧名 - 不要在
catch里吞掉错误又不记录(catch {})—— 这会让问题彻底消失 -
try...catch有轻微性能开销,不要无脑包裹整个函数体,只包明确可能出错的最小代码段











