JavaScript throw 语句

JavaScript throw 语句简介

我们平常在开发的时候都知道,当程序遇到无法处理的情况时(比如给一个 const 常量赋新值),JavaScript 解释器会自动抛出一个错误对象。

在 JavaScript 中,如果我们希望 “手动” 地创建和抛出一个自定义的错误对象,此时就可以使用 throw 语句来实现。

语法:

throw expression

说明:

expression 是你要抛出的值。虽然它可以是任何类型的值,比如数字、字符串、布尔值、对象等。不过一般情况下,我们都是抛出一个 Error 对象的实例。这是因为 Error 对象提供了标准的错误属性(比如 name 和 message),这样会更加统一和规范。

当使用 throw 语句抛出错误之后,它之后的代码将不会被执行,然后 JavaScript 会查找最近的 catch 块。

throw 语句一般配合 try...catch 语句 一起使用。其中,throw 抛出的错误一般由 try...catch 语句中的 “catch 块” 来捕获和处理,以防止程序的崩溃。

示例 1:throw 抛出字符串

function checkInput(value) {
    // 如果值为空,则抛出一个字符串
    if (value === "") {
        throw "输入值不能为空!";
    }
    // 如果值不为空,则返回该值
    return "输入值:" + value;
}

try {
    const result = checkInput("");
    console.log(result);
} catch (error) {
    console.log("捕获到错误信息:" + error);
}

运行结果如下。

捕获到错误信息:输入值不能为空!

分析:

虽然 throw 语句可以直接抛出字符串,但这种方式丢失了错误的类型、堆栈信息等重要信息。在实际开发中,我们不推荐使用这种方式来进行复杂的错误处理。

示例 2:throw 抛出 Error 对象

function checkInput(value) {
    // 如果值为空,则抛出一个字符串
    if (value === "") {
        throw new Error("输入值不能为空!");
    }
    // 如果值不为空,则返回该值
    return "输入值:" + value;
}

try {
    const result = checkInput("");
    console.log(result);
} catch (error) {
    console.log("错误名称 (name):" + error.name);
    console.log("错误信息 (message):" + error.message);
}

运行结果如下。

错误名称 (name):Error
错误信息 (message):输入值不能为空!

分析:

通过 error 对象的 name 属性,我们可以获取错误名称。通过 error 对象的 message 属性,我们可以获取错误信息。

示例 3:throw 抛出内置错误对象

function calculateDiscount(price) {
    if (typeof price !== "number" || price < 0) {
        throw new TypeError("Price 必须是一个非负数字!");
    }
    return price * 0.8;
}

try {
    const finalPrice = calculateDiscount(-100);
    console.log("最终价格:" + finalPrice);
} catch (error) {
    console.log("错误名称 (name):" + error.name);
    console.log("错误信息 (message):" + error.message);
}

运行结果如下。

错误名称 (name):TypeError
错误信息 (message):Price 必须是一个非负数字!

分析:

在这个例子中,我们通过 throw 来抛出 TypeError(JavaScript 内置的错误类型之一),这样不仅能提供错误信息,还能准确地指示错误的类型,从而大大提高了代码的可维护性。

throw 再次抛出错误

在实际开发中,有时候我们在 catch 里处理不了这个错误,或者只想记录一下日志,然后可以使用 throw 语句将错误继续往外抛,让外层去处理。这也是 throw 的核心用法之一。

示例 4:throw 再次抛出错误

function processData(jsonString) {
    try {
        const user = JSON.parse(jsonString);
        console.log(user.name);
    } catch (error) {
        // 1. 如果是语法错误(JSON 格式不对),我们在这里解决
        if (error instanceof SyntaxError) {
            console.log("数据格式有误,请检查 JSON 格式。");
        } else {
            // 2. 如果是其他未知的错误,我们解决不了,于是再次抛出,给外面处理
            throw error;
        }
    }
}

try {
    // 故意传入一个 null,这会导致 JSON.parse 抛出 TypeError(而不是 SyntaxError)
    processData(null);
} catch (error) {
    console.log(error.name);
}

运行结果如下。

TypeError

分析:

在这个例子中,processData 函数内部有一个 try...catch。如果是 SyntaxError(比如 JSON 格式不对),内部的 catch 块就直接处理了(打印提示)。但假如我们传入的是 null,此时会导致 JSON.parse 抛出一个 TypeError。而内部的 catch 块发现这不是 SyntaxError,于是执行 throw error 将其再次抛出。

最后,最外层的 catch 块捕获到了这个被 “转手” 出来的错误。这种方式能让我们把 “能处理的错误” 就地解决,把 “不能处理的错误” 交给上层去处理。

深入了解 throw 语句

在 JavaScript 中,当 throw 语句执行时,它会立即中断当前函数的执行,然后查找它外层是否有 try...catch 语句。如果有的话,则直接跳转到 catch 块中去。

示例 5:throw 会中断函数执行

// 定义函数
function processData(data) {
    try {
        if (!data) {
            throw new Error("Data 不允许为空!");    // 中断点
        }
        // 只有在没有抛出异常时,才会执行下面的代码
        console.log("数据处理成功!"); 
    } catch (error) {
        console.log("错误信息:" + error.message);
    } finally {
        // 无论如何,finally 都会执行
        console.log("清理操作完成!");
    }
}

// 调用函数
processData(null);

运行结果如下。

错误信息:Data 不允许为空!
清理操作完成!
给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号