ZetCode

JavaScript throw 关键字

最后修改于 2025 年 4 月 16 日

在本文中,我们将展示如何使用 JavaScript 中的 throw 关键字来处理错误。

throw 关键字

throw 关键字用于在 JavaScript 中创建自定义错误。 当它被执行时,它会停止当前函数的执行并将控制权传递给调用堆栈中的第一个 catch 块。 如果不存在 catch 块,程序将终止。

您可以抛出任何表达式,但最佳实践是抛出 Error 对象或继承自 Error 的对象。 这提供了一致的错误处理和对堆栈跟踪的访问。 throw 语句通常与 try-catch 块一起使用,以进行适当的错误处理。

与某些语言不同,JavaScript 允许抛出任何值 - 字符串、数字、对象。 但是,建议使用 Error 对象以获得更好的调试效果。 throw 语句对于创建健壮的、容错的代码至关重要。

使用字符串的基本 throw

最简单的例子是抛出一个字符串作为错误。

main.js
try {
    throw "An error occurred";
} catch (e) {
    console.log("Caught:", e);
}

这演示了抛出一个原始字符串值。 虽然可行,但不建议在生产代码中使用。 catch 块接收抛出的字符串并将其记录下来。 这展示了基本的 throw-catch 机制。

$ node main.js
Caught: An error occurred

抛出 Error 对象

一个更好的做法是抛出一个 Error 对象。

main.js
try {
    throw new Error("Something went wrong");
} catch (e) {
    console.log("Error name:", e.name);
    console.log("Error message:", e.message);
    console.log("Stack trace:", e.stack);
}

Error 对象比原始值提供更多信息。 它们包含用于调试的堆栈跟踪。 此示例显示了访问错误的属性。 Error 构造函数接受一条描述错误的 message。

$ node main.js
Error name: Error
Error message: Something went wrong
Stack trace: Error: Something went wrong
    at Object.<anonymous> (...)

自定义错误类

您可以通过扩展 Error 来创建自定义错误类。

main.js
class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.name = "ValidationError";
    }
}

try {
    throw new ValidationError("Invalid input");
} catch (e) {
    if (e instanceof ValidationError) {
        console.log("Custom error caught:", e.name, e.message);
    }
}

这为验证失败创建了一个专门的错误类型。 自定义错误允许更具体的错误处理。 instanceof 检查验证了错误类型。 这种模式对于创建特定于领域的错误层次结构很有用。

$ node main.js
Custom error caught: ValidationError Invalid input

在函数中抛出

函数可以抛出错误,这些错误会被调用代码捕获。

main.js
function divide(a, b) {
    if (b === 0) {
        throw new Error("Division by zero");
    }
    return a / b;
}

try {
    console.log(divide(10, 0));
} catch (e) {
    console.log("Error:", e.message);
}

这展示了在检测到无效输入时从函数抛出错误。 调用代码处理潜在的错误。 这是输入验证的常见模式。 错误会在调用堆栈中传播,直到被捕获。

$ node main.js
Error: Division by zero

重新抛出错误

您可以捕获一个错误,部分处理它,然后重新抛出它。

main.js
function processData(data) {
    if (!data) {
        throw new Error("No data provided");
    }
    // Process data...
}

try {
    try {
        processData(null);
    } catch (e) {
        console.log("Logging error:", e.message);
        throw e; // Rethrow
    }
} catch (e) {
    console.log("Outer catch:", e.message);
}

这演示了在多个级别上的错误处理。 内部 catch 在重新抛出错误之前记录该错误。 外部 catch 处理重新抛出的错误。 当不同的层需要以不同的方式处理错误时,这很有用。

$ node main.js
Logging error: No data provided
Outer catch: No data provided

抛出非 Error 对象

虽然不推荐,但您可以抛出任何 JavaScript 值。

main.js
try {
    throw { 
        code: 404, 
        message: "Not Found",
        timestamp: new Date()
    };
} catch (e) {
    console.log(`Error ${e.code} at ${e.timestamp}: ${e.message}`);
}

这抛出一个自定义对象而不是一个 Error。 虽然灵活,但这种方法缺少堆栈跟踪和标准错误属性。 catch 块必须知道对象的结构。 这种模式有时用于 API 错误响应。

$ node main.js
Error 404 at Wed Apr 16 2025 12:00:00 GMT+0000: Not Found

实际用例:输入验证

这是一个使用 throw 进行输入验证的实际例子。

main.js
function registerUser(user) {
    if (!user.name) {
        throw new Error("Name is required");
    }
    if (user.age < 18) {
        throw new Error("User must be 18 or older");
    }
    // Registration logic...
    console.log("User registered:", user.name);
}

try {
    registerUser({ name: "John", age: 16 });
} catch (e) {
    console.log("Registration failed:", e.message);
}

这在处理之前验证用户输入。 每个验证失败都会抛出一个描述性错误。 调用代码优雅地处理任何验证错误。 这种模式确保无效数据不会在应用程序中进一步进行。

$ node main.js
Registration failed: User must be 18 or older

来源

throw - 语言参考

在本文中,我们已经演示了如何使用 throw 关键字来处理 JavaScript 中的错误。

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。 迄今为止,我撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

查看 所有 JavaScript 教程。