try-catch仅捕获同步错误,异步错误需在回调内单独处理;catch可接收任意值但推荐Error实例以保留堆栈;finally中return会覆盖try/catch的返回值;顶层不应盲目包裹,应聚焦明确边界和错误响应。

try-catch只能捕获同步错误
异步代码(比如 setTimeout、fetch、Promise 回调)抛出的错误,不会被外层 try-catch 捕获。这是最常踩的坑——你以为包住了,其实没包住。
- ✅ 正确做法:在异步回调内部单独加
try-catch,或用.catch()处理 Promise 拒绝 - ❌ 错误写法:
try { setTimeout(() => { throw new Error('这个错误抓不到'); }, 0); } catch (e) { console.log('永远不会执行到这里'); } - Promise 场景下,优先用
async/await+try-catch,比链式.then().catch()更直观
catch参数必须是Error实例吗?
不是。JavaScript 允许 throw 任意值(字符串、数字、对象),catch 参数就是那个值本身。但不推荐抛出非 Error 实例,因为会丢失堆栈信息,调试困难。
- ⚠️ 风险示例:
throw '请求失败'; // 没有 stack,难定位
- ✅ 推荐写法:
throw new Error('请求失败'); // 自动带 stack - 如果必须抛原始值,至少手动补上
stack或用console.trace()辅助排查
finally里能改变返回值吗?
可以,但只对 return 语句有效,且行为取决于 finally 是否自己 return。
- 如果
finally不return,则原函数的return值生效 - 如果
finally有return,它会覆盖前面所有return(包括catch中的) - 示例:
function test() { try { return 'from try'; } catch (e) { return 'from catch'; } finally { return 'from finally'; // ✅ 最终返回这个 } } - 多数情况下,
finally应只做清理(如关闭连接、重置状态),避免干扰控制流
要不要在顶层加try-catch?
不要盲目加。全局 try-catch(比如包住整个脚本)掩盖问题,让错误静默失败,反而更难调试。
立即学习“Java免费学习笔记(深入)”;
- ✅ 合理场景:封装第三方 SDK 调用、处理用户输入等明确可能出错的边界操作
- ❌ 反模式:
try { // 几百行业务逻辑全包在这里 } catch (e) { console.error(e); // 错误来源模糊,堆栈被截断 } - 真正需要兜底时,用
window.onerror或window.addEventListener('error')捕获未处理异常,配合PromiseRejectionEvent补全异步错误










