throw语句用于抛出一个异常。
throw "错误信息";
throw new Error("错误信息");
throw {
name: "自定义错误",
message: "错误详情"
};
// 抛出字符串
function divide(a, b) {
if (b === 0) {
throw "除数不能为零";
}
return a / b;
}
// 抛出Error对象
function validateAge(age) {
if (age < 0) {
throw new Error("年龄不能为负数");
}
return age;
}
// 抛出自定义错误
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError("用户名不能为空");
}
}
// 参数验证
function setAge(age) {
if (typeof age !== "number") {
throw new TypeError("年龄必须是数字");
}
if (age < 0 || age > 150) {
throw new RangeError("年龄必须在0-150之间");
}
this.age = age;
}
// 状态检查
class Connection {
constructor() {
this.connected = false;
}
send(data) {
if (!this.connected) {
throw new Error("连接未建立");
}
console.log("发送数据:", data);
}
}
try-catch语句用于捕获和处理异常。
try {
// 可能出错的代码
} catch (error) {
// 处理错误
}
// 示例
try {
let result = divide(10, 0);
} catch (error) {
console.log("发生错误:", error);
}
try {
JSON.parse("无效的JSON");
} catch (e) {
console.log(e.name); // SyntaxError
console.log(e.message); // 错误详情
console.log(e.stack); // 错误堆栈
}
try {
// 可能抛出多种错误的代码
let data = JSON.parse(input);
process(data);
} catch (error) {
if (error instanceof SyntaxError) {
console.log("JSON格式错误:", error.message);
} else if (error instanceof TypeError) {
console.log("类型错误:", error.message);
} else if (error instanceof RangeError) {
console.log("范围错误:", error.message);
} else {
console.log("未知错误:", error.message);
}
}
try {
try {
throw new Error("内部错误");
} catch (e) {
console.log("内部捕获:", e.message);
throw e; // 重新抛出
}
} catch (e) {
console.log("外部捕获:", e.message);
}
finally块无论是否发生异常都会执行。
try {
// 可能出错的代码
} catch (error) {
// 处理错误
} finally {
// 无论是否出错都会执行
}
// 示例
function readFile(path) {
let file = openFile(path);
try {
return file.read();
} finally {
file.close(); // 确保关闭文件
}
}
function test() {
try {
console.log("try");
return "返回值";
} catch (e) {
console.log("catch");
} finally {
console.log("finally");
}
}
console.log(test());
// try
// finally
// 返回值
// finally的return会覆盖try的return
function test() {
try {
return "try返回";
} finally {
return "finally返回";
}
}
console.log(test()); // "finally返回"
// 建议:不要在finally中使用return
function processResource() {
let resource = acquireResource();
try {
resource.doSomething();
resource.doAnother();
} catch (e) {
console.log("处理出错:", e);
} finally {
resource.release(); // 确保释放资源
}
}
JavaScript内置了多种错误类型。
| 错误类型 | 说明 | 示例场景 |
|---|---|---|
| Error | 通用错误 | 自定义错误 |
| SyntaxError | 语法错误 | JSON解析失败 |
| TypeError | 类型错误 | 调用不存在的方法 |
| RangeError | 范围错误 | 递归溢出 |
| ReferenceError | 引用错误 | 访问未定义变量 |
| URIError | URI错误 | encodeURI参数错误 |
// 基本创建
let error1 = new Error("出错了");
let error2 = Error("出错了"); // 可以省略new
// 带文件名和行号
let error3 = new Error("出错了", "script.js", 10);
// 访问属性
console.log(error1.name); // "Error"
console.log(error1.message); // "出错了"
console.log(error1.stack); // 堆栈信息
// SyntaxError
eval("无效代码"); // SyntaxError
// TypeError
null.foo(); // TypeError: Cannot read property 'foo' of null
// RangeError
function recurse() { recurse(); }
recurse(); // RangeError: Maximum call stack size exceeded
// ReferenceError
console.log(undeclaredVar); // ReferenceError: undeclaredVar is not defined
// URIError
decodeURI("%"); // URIError: URI malformed
通过继承Error创建自定义错误。
class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}
try {
throw new CustomError("自定义错误信息");
} catch (e) {
console.log(e.name); // "CustomError"
console.log(e.message); // "自定义错误信息"
}
class HttpError extends Error {
constructor(message, statusCode) {
super(message);
this.name = "HttpError";
this.statusCode = statusCode;
}
}
try {
throw new HttpError("资源未找到", 404);
} catch (e) {
console.log(e.name); // "HttpError"
console.log(e.message); // "资源未找到"
console.log(e.statusCode); // 404
}
// 验证错误
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
function validateUser(user) {
if (!user.name) {
throw new ValidationError("用户名必填", "name");
}
if (!user.email) {
throw new ValidationError("邮箱必填", "email");
}
}
// 数据库错误
class DatabaseError extends Error {
constructor(message, query) {
super(message);
this.name = "DatabaseError";
this.query = query;
}
}
// 权限错误
class PermissionError extends Error {
constructor(message, requiredRole) {
super(message);
this.name = "PermissionError";
this.requiredRole = requiredRole;
}
}
// 不推荐:捕获所有错误但不处理
try {
doSomething();
} catch (e) {
// 什么都不做
}
// 推荐:只捕获需要处理的错误
try {
doSomething();
} catch (e) {
if (e instanceof SpecificError) {
handleSpecificError(e);
} else {
throw e; // 重新抛出无法处理的错误
}
}
// 不推荐
throw new Error("错误");
// 推荐
throw new Error(`用户${userId}不存在,请检查用户ID是否正确`);
// 不推荐
if (!user) {
throw new Error("用户不存在");
}
// 推荐
class UserNotFoundError extends Error {
constructor(userId) {
super(`用户${userId}不存在`);
this.name = "UserNotFoundError";
this.userId = userId;
}
}
if (!user) {
throw new UserNotFoundError(userId);
}
try {
await processPayment(order);
} catch (e) {
logger.error("支付处理失败", {
orderId: order.id,
error: e.message,
stack: e.stack
});
notifyUser("支付失败,请重试");
}
// Promise
fetch(url)
.then(response => response.json())
.catch(error => console.error("请求失败:", error));
// async/await
async function fetchData() {
try {
const response = await fetch(url);
return await response.json();
} catch (error) {
console.error("请求失败:", error);
throw error;
}
}
function safeExecute(fn, fallback) {
try {
return fn();
} catch (e) {
console.error("执行出错:", e);
return fallback;
}
}
const result = safeExecute(
() => JSON.parse(data),
{} // 解析失败时返回空对象
);
掌握了异常处理后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
⚠️ 东巴文寄语:异常处理是程序健壮性的保障,合理的异常处理能让程序在遇到意外情况时优雅地处理,而不是直接崩溃。在 db-w.cn,我们教你写出更健壮的代码!