JavaScript 常见错误及处理指南
一、错误类型与机制
JavaScript中的错误主要分为以下类型:
- 语法错误(SyntaxError)
- 代码不符合JavaScript语法规则时抛出,IDE通常能直接检测
- 示例:
console.log(myvarible)
(变量名拼写错误)
- 运行时错误(ReferenceError)
- 访问未定义变量时触发,如
console.log(x)
(x未声明)
- 访问未定义变量时触发,如
- 类型错误(TypeError)
- 对非对象类型进行操作时发生,如
null.f()
- 对非对象类型进行操作时发生,如
- 范围错误(RangeError)
- 数值超出有效范围时触发,如
new Array(-1)
- 数值超出有效范围时触发,如
- 逻辑错误
- 代码能运行但结果不符合预期,最难调试的类型
// 错误类型检测示例
try {
let arr = new Array(-1); // 触发RangeError
} catch (error) {
if (error instanceof RangeError) {
console.error("数值超出范围:", error.message);
}
}
二、错误捕获技术
1. 基础捕获结构
try {
// 可能出错的代码
JSON.parse(invalidJson);
} catch (error) {
console.error(`错误类型: ${error.name},信息: ${error.message}`);
} finally {
console.log("清理资源操作"); // 始终执行
}
2. 条件捕获块
try {
fetchData();
} catch (e) {
if (e instanceof TypeError) {
handleTypeError(e);
} else if (e instanceof RangeError) {
handleRangeError(e);
} else {
throw e; // 重新抛出未处理错误
}
}
三、异步错误处理
1. Promise链式处理
fetch('/api/data')
.then(response => {
if (!response.ok) throw new Error('网络响应异常');
return response.json();
})
.catch(error => {
console.error("请求失败:", error); // 捕获整个链条的错误
});
2. async/await处理
async function loadUserData() {
try {
const response = await fetch('/api/users');
if (!response.ok) throw new Error('数据加载失败');
return await response.json();
} catch (error) {
logToServer(error); // 异步错误捕获
}
}
四、自定义错误创建
1. 类继承方式
class ValidationError extends Error {
constructor(field, message) {
super(`字段${field}验证失败: ${message}`);
this.name = "ValidationError";
this.field = field;
}
}
// 使用示例
throw new ValidationError('email', '格式无效');
2. 构造函数模式
function NetworkError(message, statusCode) {
this.message = message;
this.status = statusCode;
this.stack = new Error().stack;
}
NetworkError.prototype = Object.create(Error.prototype);
五、全局错误处理
1. 同步错误捕获
window.onerror = (message, source, lineno, colno, error) => {
sendErrorToAnalytics({
message,
file: source,
line: `${lineno}:${colno}`,
stack: error.stack
});
return true; // 阻止默认错误提示
};
2. Promise未处理拒绝
window.addEventListener('unhandledrejection', event => {
console.warn(`未处理的Promise拒绝: ${event.reason}`);
event.preventDefault(); // 避免控制台报错
});
六、最佳实践与工具
1. 错误日志规范
function logError(error) {
console.error(`[${new Date().toISOString()}] ${error.name}: ${error.message}`);
if (error.stack) console.debug("调用栈:", error.stack);
if (error.cause) console.log("根本原因:", error.cause); // 错误链追踪
}
2. 用户友好处理
function showUserAlert(error) {
const userMessages = {
NetworkError: "网络连接异常,请检查网络",
TimeoutError: "请求超时,请重试",
default: "系统繁忙,请稍后再试"
};
alert(userMessages[error.name] || userMessages.default);
}
3. 调试工具对比
工具类型 | 代表工具 | 核心功能 |
---|---|---|
浏览器内置 | Chrome DevTools | 实时错误提示、断点调试、调用栈分析 |
监控平台 | Sentry/Rollbar | 错误聚合、用户影响分析、源映射解析 |
测试框架 | Jest/Mocha | 自动化错误场景测试、覆盖率检测 |
七、实战应用场景
1. JSON解析安全处理
function safeParse(jsonString) {
try {
return JSON.parse(jsonString);
} catch {
console.warn("JSON解析失败,返回空对象");
return {}; // 避免进程中断
}
}
2. 表单验证错误处理
function validateForm(data) {
if (!data.email.includes('@'))
throw new ValidationError('email', '邮箱格式无效');
if (data.password.length < 8)
throw new ValidationError('password', '密码至少8位');
}
// 调用处
try {
validateForm(userInput);
} catch (error) {
if (error instanceof ValidationError) {
highlightErrorField(error.field, error.message);
}
}
3. 资源加载容错
async function loadExternalResource(url) {
try {
const resource = await fetchResource(url);
return resource;
} catch (error) {
if (navigator.onLine) {
throw new NetworkError(`资源加载失败: ${url}`);
} else {
return loadFromCache(url); // 离线回退策略
}
}
}
总结
系统梳理了JavaScript错误处理的核心知识体系,涵盖从基础错误类型识别到高级异步处理策略。可结合错误监控平台(如Sentry)和自动化测试(如Jest),可形成预防-捕获-分析-优化的完整质量闭环。
扩展阅读推荐:
- 《Effective JavaScript》- 包含68个高效JS实践
- 《JavaScript设计模式》- 容错设计模式详解
- 《前端架构设计》- 错误监控系统设计