JavaScript错误处理需分场景:try...catch仅捕获同步异常;异步错误需用.catch()、await+try...catch或window.onerror/onunhandledrejection全局兜底;调试应结合debugger、DevTools面板及上下文上报策略。

JavaScript 错误处理不是加个 try...catch 就算完事,关键得知道什么时候该捕获、捕获后怎么处理、以及哪些错误根本捕不到。
哪些错误能被 try...catch 捕获
try...catch 只能捕获同步执行中抛出的异常(throw 或运行时错误),对异步操作(如 setTimeout、Promise、事件回调)中的错误默认无效。
- 能捕获:
try { JSON.parse('{ "invalid": }'); // SyntaxError } catch (e) { console.log(e.name); // "SyntaxError" } - 不能直接捕获:
try { setTimeout(() => { throw new Error('boom'); }, 0); } catch (e) { // 这里永远不会执行 } - Promise 错误需用
.catch()或await+try...catch:async function fetchUser() { try { const res = await fetch('/api/user'); if (!res.ok) throw new Error(`HTTP ${res.status}`); return await res.json(); } catch (e) { console.error('获取用户失败:', e.message); } }
window.onerror 和 window.onunhandledrejection 补漏
浏览器环境里,这两个全局钩子是捕获“漏网之鱼”的最后防线:前者抓同步/异步脚本错误(包括 script 标签加载失败),后者专抓未处理的 Promise 拒绝。
-
window.onerror参数顺序固定:(message, source, lineno, colno, error),返回true可阻止默认错误上报:window.onerror = function (msg, url, line, col, err) { console.error('JS error:', { msg, url, line, col, stack: err?.stack }); return true; // 阻止控制台重复打印 }; -
window.onunhandledrejection接收event.reason,可能是Error实例,也可能是普通值:window.onunhandledrejection = function (event) { console.error('Unhandled rejection:', event.reason); // 注意:event.preventDefault() 在部分旧版 Safari 不生效 }; - 两者都**无法捕获 CORS 脚本错误的详细信息**——浏览器会统一返回
"Script error.",需在标签加crossorigin属性并确保服务端返回Access-Control-Allow-Origin。
调试时别只盯 console.log,善用 debugger 和 DevTools
debugger 是语句级断点,比打日志更精准;配合 Chrome / Edge 的 Sources 面板,能查看作用域变量、修改值、逐行执行。
立即学习“Java免费学习笔记(深入)”;
- 在可疑代码前插入:
function calculateTotal(items) { debugger; // 执行到这里会暂停 return items.reduce((sum, item) => sum + item.price, 0); } - 条件断点更高效:右键行号 → “Edit breakpoint” → 输入表达式,比如
items.length === 0,避免手动触发多次。 - Network 面板里点击某个请求 → “Preview” 或 “Response” 查看接口实际返回,比盲目猜
undefined原因快得多。 - Performance 面板录制页面交互,定位卡顿是否由某次错误重试或无限循环导致(例如
requestAnimationFrame中没做终止判断)。
错误分类与上报策略要区分对待
不是所有错误都值得上报。网络超时、用户取消操作这类预期行为,不该刷屏监控系统;而 TypeError: Cannot read property 'x' of undefined 这类明显代码缺陷才需要告警。
- 过滤低价值错误:
if (error.name === 'TypeError' && error.message.includes('undefined')) { // 上报 } else if (error.message.includes('NetworkError') || error.message.includes('AbortError')) { // 忽略或仅本地记录 } - 收集必要上下文:当前 URL、用户操作路径(如
history.state)、设备类型、错误堆栈(error.stack)。 - 避免重复上报:对同一错误堆栈做简单哈希(如取前 100 字符 MD5),5 分钟内相同哈希只报一次。
真正难的不是写 catch,而是判断这个错误该不该吞掉、该不该重试、该不该通知用户、该不该触发降级逻辑——这些决策藏在业务流程里,没法靠工具自动补全。










