本文详解 JavaScript 中异常的抛出与处理机制。涵盖 throw 语句的使用、基本类型与对象类型异常的区别,重点解析 Error 类的 stack、message 等属性及调用栈追踪。同时介绍 try...catch...finally 标准处理流程、ES10 简化语法及常见系统异常类型,帮助开发者构建健壮的错误处理逻辑。
抛出异常
在 JavaScript 开发中,处理异常或错误情况是常见需求。例如,当某个函数期望接收 Number 类型的参数,但实际调用时传入了字符串,此时需要发出明确提醒。这种情况下,可以使用 throw 语句来主动抛出一个异常。
// 例 1
function fn(num) {
if (typeof num !== 'number') throw '需传入数字'
console.log(num) // 不会打印
}
fn('0')
console.log('不会执行')执行例 1 的代码结果如下:

由于第 7 行传入了字符串,导致第 3 行 throw 语句被执行。在函数 fn 内部,后续代码将不再执行,这与 return 的行为一致。因为第 7 行调用 fn 函数时未进行异常捕获,程序会直接终止,导致第 8 行代码无法执行。
抛出的表达式类型
基本数据类型
在例 1 中,我们抛出了一个基本数据类型——字符串。实际上,还可以抛出数字等其他基本类型的数据。
对象
我们也可以抛出一个对象,以便传递更丰富的信息:
// 例 1.1
function fn(num) {
if (typeof num !== 'number')
throw {
code: -1,
msg: '类型错误'
}
console.log(num)
}类的实例对象
如果每次抛出异常都像例 1.1 那样手动构造对象,代码会显得繁琐。因此,可以创建一个类(如例 1.2 中的 myError),用于生成包含错误信息的对象:
// 例 1.2
class myError {
constructor(code, msg) {
this.code = code
this.msg = msg
}
}
function fn(num) {
if (typeof num !== 'number') throw new myError(-1, '类型错误')
console.log(num)
}这样执行 fn 时,若未进行异常捕获,将打印如下报错信息:

Error 类的实例对象
实际上,无需自定义类来创建错误对象,JavaScript 原生提供了 Error 类。构建错误对象时,只需传入错误的描述信息即可:
// 例 1.3
function fn(num) {
if (typeof num !== 'number') throw new Error('类型错误')
console.log(num)
}
fn('0')在 Node.js 环境中执行例 1.3,所得结果比我们自己定义的 myError 多出了函数的调用栈信息:

我们可以直接通过 Error 实例对象的 stack 属性查看调用栈,此外还有 message 和 name 属性:
// 例 1.3.1
function fn(num) {
if (typeof num !== 'number') {
const err = new Error('类型错误')
console.log('name:', err.name)
console.log('message:', err.message)
console.log('stack:', err.stack)
throw err
}
console.log(num)
}
fn('0')在 Node.js 中执行例 1.3.1,第 5 至 7 行的输出结果如下:

如果对例 1.3 进行改造,不直接执行 fn('0'),而是让它在 bar 函数内被调用,然后在 foo 函数内调用 bar,最后执行 foo():
// 例 1.3.2
function fn(num) {
if (typeof num !== 'number') throw new Error('类型错误')
console.log(num)
}
function foo() {
bar()
}
function bar() {
fn('0')
}
foo()可以看到调用栈信息又增加了 2 条记录:

Error 的子类
Error 还有几个子类。例如上述例子属于类型错误,可以使用更具体的 TypeError 类来生成错误对象:
// 例 1.4
function fn(num) {
if (typeof num !== 'number') throw new TypeError('类型错误')
console.log(num)
}
fn('0')此外还有诸如引用错误 ReferenceError 和语法错误 SyntaxError 等。
处理异常
若一个异常被抛出且最终未被捕获,将导致程序终止执行。这里强调“最终”,是因为如果函数执行时抛出的异常未被处理,异常会传递给调用该函数的上层函数。以例 1.3.2 为例,第 10 行执行 fn('0') 导致抛出异常,且未在第 10 行对 fn('0') 进行捕获,异常便会传递给第 7 行的 bar(),再传递给第 12 行即最顶层的 foo()。此时仍未处理异常,导致报错并终止程序运行。只要在异常传递过程中的任何一处使用 try...catch 语句进行捕获,例如下面的例 2,程序就不会终止。异常将作为参数传递给 catch 子句,即第 15 行的 error:
// 例 2
function fn(num) {
if (typeof num !== 'number') throw new Error('类型错误')
console.log(num) // 不会执行
}
function foo() {
bar()
}
function bar() {
fn('0')
}
try {
foo()
console.log('我不会继续执行')
} catch (error) {
console.log('error:', error.message)
} finally {
console.log('我无论是否有异常抛出都会执行')
}
console.log('我会继续执行')执行例 2 的结果如下:

可以看到例 2 第 17 行还有一个 finally 子句,无论是否有异常抛出或捕获,该子句总会执行。
P.S. 从 ES10(ES2019)开始,第 15 行的 catch 子句可以省略 (error),即不去获取错误信息。
js中常见的系统异常:
- EvalError: raised when an error occurs executing code in eval() 当一个错误发生在()执行的代码
- RangeError: raised when a numeric variable or parameter is outside of its valid range 当一个数值变量或参数超出其有效范围时引发的
- ReferenceError: raised when de-referencing an invalid reference 无效的饮用
- SyntaxError: raised when a syntax error occurs while parsing code in eval() 当发生语法错误在()解析代码,而
- TypeError: raised when a variable or parameter is not a valid type 当一个变量或参数不是一个有效的类型时引发
- URIError: raised when encodeURI() or decodeURI() are passed invalid parameters 当encodeuri()或decodeuri()传递了无效的参数
注:上面的六种异常对象都继承自Error对象:
try {
throw new Error("Whoops!");
} catch (e) {
console.log(e.name + ": " + e.message);
}总结
到此这篇关于JS中异常抛出和处理方法的文章就介绍到这了,更多相关JS异常抛出与处理内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!