JavaScript 快速入门

错误处理

在 JavaScript 中,错误处理是一种重要的编程实践,它可以帮助我们优雅地处理程序运行时可能出现的异常情况。

try...catch

try...catch 是 JavaScript 中最基本的错误处理机制。

try {
// 可能抛出错误的代码
const result = someFunction();
console.log(result);
} catch (error) {
// 处理错误
console.error('发生错误:', error.message);
}

基本用法

function divide(a, b) {
if (b === 0) {
throw new Error('除数不能为零');
}
return a / b;
}
try {
console.log(divide(10, 2)); // 5
console.log(divide(10, 0)); // 抛出错误
} catch (error) {
console.error('计算错误:', error.message); // 计算错误: 除数不能为零
}

finally 块

finally 块中的代码无论是否发生错误都会执行,通常用于清理资源。

let fileHandle;
try {
fileHandle = openFile('data.txt');
processFile(fileHandle);
} catch (error) {
console.error('处理文件时出错:', error.message);
} finally {
// 无论是否发生错误,都关闭文件
if (fileHandle) {
closeFile(fileHandle);
}
}

嵌套的 try...catch

可以在 try 块内部嵌套另一个 try...catch 结构。

try {
try {
throw new Error('内部错误');
} catch (innerError) {
console.error('捕获到内部错误:', innerError.message);
throw new Error('外部错误'); // 重新抛出错误
}
} catch (outerError) {
console.error('捕获到外部错误:', outerError.message);
}

错误类型

JavaScript 提供了多种内置的错误类型,每种类型用于表示特定类型的错误。

Error

Error 是所有错误类型的基类。

const error = new Error('发生错误');
console.log(error.name); // 'Error'
console.log(error.message); // '发生错误'
console.log(error.stack); // 错误堆栈

TypeError

TypeError 表示值的类型不符合预期。

try {
const num = 42;
num.toLowerCase(); // 数字没有 toLowerCase 方法
} catch (error) {
console.log(error instanceof TypeError); // true
console.log(error.message); // 'num.toLowerCase is not a function'
}

ReferenceError

ReferenceError 表示引用了一个不存在的变量。

try {
console.log(undefinedVariable); // 未定义的变量
} catch (error) {
console.log(error instanceof ReferenceError); // true
console.log(error.message); // 'undefinedVariable is not defined'
}

SyntaxError

SyntaxError 表示语法错误。

try {
eval('if (true) {'); // 语法错误
} catch (error) {
console.log(error instanceof SyntaxError); // true
console.log(error.message); // 'Unexpected token }'
}

RangeError

RangeError 表示数值超出有效范围。

try {
const arr = new Array(-1); // 数组长度不能为负数
} catch (error) {
console.log(error instanceof RangeError); // true
console.log(error.message); // 'Invalid array length'
}

错误传播

错误可以从一个函数传播到另一个函数,直到被捕获或到达全局作用域。

function level3() {
throw new Error('level3 错误');
}
function level2() {
try {
level3();
} catch (error) {
console.log('level2 捕获错误:', error.message);
throw error; // 重新抛出错误
}
}
function level1() {
try {
level2();
} catch (error) {
console.log('level1 捕获错误:', error.message);
}
}
level1();
// level2 捕获错误: level3 错误
// level1 捕获错误: level3 错误

自定义错误

可以通过继承 Error 类来创建自定义错误类型。

class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError('用户名不能为空');
}
if (!user.email) {
throw new ValidationError('邮箱不能为空');
}
if (!user.email.includes('@')) {
throw new ValidationError('邮箱格式不正确');
}
}
try {
validateUser({ name: '', email: 'invalid-email' });
} catch (error) {
if (error instanceof ValidationError) {
console.error('验证错误:', error.message);
} else {
console.error('未知错误:', error.message);
}
}

最佳实践

只捕获预期的错误

try {
// 可能抛出错误的代码
processData();
} catch (error) {
// 只处理预期的错误
if (error instanceof ValidationError) {
console.error('验证错误:', error.message);
} else {
// 重新抛出未预期的错误
throw error;
}
}

提供有用的错误信息

function divide(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new TypeError(`参数必须是数字,但收到了 ${typeof a} 和 ${typeof b}`);
}
if (b === 0) {
throw new Error('除数不能为零');
}
return a / b;
}
try {
divide('10', 2);
} catch (error) {
console.error(error.message); // 参数必须是数字,但收到了 string 和 number
}

记录错误日志

function logError(error, context = {}) {
console.error('错误时间:', new Date().toISOString());
console.error('错误类型:', error.name);
console.error('错误消息:', error.message);
console.error('错误堆栈:', error.stack);
console.error('上下文信息:', context);
// 在实际应用中,可以将错误发送到服务器或日志服务
// sendErrorToServer(error, context);
}
try {
// 可能抛出错误的代码
processData();
} catch (error) {
logError(error, { userId: 123, action: 'processData' });
}

动手试试

下面是一个简单的用户注册系统,你需要实现错误处理来验证用户输入并处理可能的错误。

Made by 捣鼓键盘的小麦 / © 2025 Front Study 版权所有