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 不允许为空!
清理操作完成!