try-catch不能捕获语法错误,因解析阶段即报SyntaxError;可捕获ReferenceError、TypeError等运行时错误及手动throw的异常;异步错误需用.catch()、await+try-catch或事件监听处理。

try catch 不能捕获语法错误
直接写错语法(比如少个括号、用错关键字)时,try catch 完全无效——因为代码根本没进入执行阶段,JS 引擎在解析阶段就报 SyntaxError 了。这类错误只能靠编辑器提示、ESLint 或构建工具提前发现。
真正能被 try catch 捕获的,是运行时错误,比如:
-
ReferenceError(访问未声明变量) -
TypeError(调用非函数、读取null的属性) -
RangeError(递归过深、数组长度非法) - 手动抛出的错误:
throw new Error('xxx')
异步代码里 try catch 失效的常见场景
在 setTimeout、Promise 回调、事件监听器里抛出的错误,不会被外层 try catch 捕获。例如:
try {
setTimeout(() => {
throw new Error('boom');
}, 0);
} catch (e) {
console.log('不会执行到这里');
}
解决方式取决于上下文:
立即学习“Java免费学习笔记(深入)”;
- Promise 内部:用
.catch()或await+try catch - 事件处理器:在回调内部单独加
try catch - 全局兜底:监听
window.onerror或window.addEventListener('error')(注意它不捕获 Promise 拒绝) - Promise 拒绝未处理:监听
unhandledrejection事件
catch 块里该不该 re-throw
不是所有错误都适合“吞掉”。如果错误表示状态异常但还能继续运行(比如某个接口返回格式不对,有 fallback),可以只记录日志、不 re-throw;但如果错误意味着后续逻辑必然失败(比如初始化关键配置失败),应该重新抛出或转为更明确的错误:
try {
const data = JSON.parse(raw);
return processData(data);
} catch (e) {
if (e instanceof SyntaxError) {
console.warn('JSON 解析失败,使用默认配置', raw);
return DEFAULT_CONFIG;
}
throw e; // 其他错误不掩盖,让上层决定
}
容易踩的坑:
- 把
catch当万能日志开关,不区分错误类型,掩盖了真正需要修复的问题 - 在
catch里做复杂异步操作(如发请求),又没处理它的失败,导致错误静默丢失 - 忽略
catch参数名,直接写catch (err)就完事,其实可以解构:catch ({ message, stack })
HTML 中 script 标签里的 try catch 要小心位置
写在内联 <script> 里没问题,但若脚本是通过 src 引入的,try catch 必须包住实际会出错的调用点,而不是只包住 import 或 require 行——模块加载本身成功了,错误可能发生在模块导出函数的执行过程中。
比如这样不行:
<script>
try {
const mod = await import('./logic.js'); // 这里不报错
} catch (e) {
// 这里捕不到 logic.js 里函数执行时的错误
}
mod.doSomething(); // 这里才可能出错
</script>
应该这样:
<script>
const mod = await import('./logic.js');
try {
mod.doSomething();
} catch (e) {
console.error('doSomething 执行失败:', e);
}
</script>
最麻烦的是第三方 SDK 的调用——它们往往在 DOM ready 后异步触发逻辑,这时候靠外层 try catch 基本没用,得依赖其文档提供的错误回调,或全局错误监听兜底。



















