ES5 / ES6 自定义错误类型比较

栏目: JavaScript · 发布时间: 6年前

内容简介:而不是 :另外,我们可以为自己的错误类型添加额外的信息字段,原生提供的错误只有

JavaScript 原生提供了7种错误类型,分别是 Error , EvalError , SyntaxError , RangeError , ReferenceError , TypeError , 和 URIError 。当我们在编写提供给其他开发者使用的库(包)时,为了在必要的时候给予开发者错误信息反馈(例如,开发者所传参数类型不正确),我们通常会抛出错误,但是原生提供的这些错误类型不够有针对性,不能让开发者一眼就能看出是我们的库所抛出的错误,所以我们需要定制自己的错误类型,当开发者错误使用库并且运行代码时能够在控制台看到我们所定义的错误类型,例如:

CustomError: something bad happened.

而不是 :

Error: something bad happened.

另外,我们可以为自己的错误类型添加额外的信息字段,原生提供的错误只有 name (错误类型), message (错误信息), stack (部分js环境提供堆栈追踪信息),这些字段可能不能够满足我们的需求,我们想给我们所抛出的错误添加一个 reason 字段来表明抛出错误的原因,那么我们就需要自定义错误类型。

自定义错误需要继承自 Error

我们自定义的错误类型最好继承自 Error 类,但这并不是强制规定,这只是一种良好的代码习惯,因为当开发者通过 try / catch 捕获到异常时,可能会进行进一步的判断:

if (error instanceof Error) { ... }

这样我们的自定义错误才能被有效捕获。

ES5 自定义错误的写法

function CustomError(message) {
    // 实例化自定义错误时所传的错误信息参数
    this.message = message
    // name 指明该错误类型(同时在控制台所打印的错误类型即由此字段指明),不指明默认为Error。
    this.name = 'CustomError'
    // 捕获到当前执行环境的堆栈追踪信息,为自定义错误实例添加 `stack` 字段进行保存,
    // 第二个参数的含义为:堆栈追踪只会展示到`CustomError`这个函数(即自定义错误的构造函数)被调用之前。
    Error.captureStackTrace(this, CustomError) 
}

// 原型链继承 (详见 JS高程 一书)
CustomError.prototype = new Error 
// 在自定义错误的原型上添加构造器函数为CustomError,
// 若不添加构造器,当获取自定义错误的构造器时,获取的是上一步`new Error`实例的原型的构造器,即`Error`构造函数
CustomError.prototype.constructor = CustomError 
复制代码

ES6 自定义错误的写法

ES6 添加了 class 这一语法糖,可以方便的写出继承关系:

class CustomError extends Error {
    constructor (message) {
        super(message)
        this.name = 'CustomError',
        // 这一步可不写,默认会保存堆栈追踪信息到自定义错误构造函数之前,
        // 而如果写成 `Error.captureStackTrace(this)` 则自定义错误的构造函数也会被保存到堆栈追踪信息
        Error.captureStackTrace(this, this.constructor)
    }
}
复制代码

测试

接下来我们通过ES 5/6 两种不同的写法来自定义错误类型后, 使用下面的代码在 Node.js 中进行测试。我们先推测堆栈追踪自栈顶向下依次应该是:

at new CustomError // 若堆栈追踪到自定义错误的构造函数时,会有此打印
at c
at b
at a
复制代码

测试代码:

// `c` 函数抛出自定义错误
function c() {
    throw new CustomError('something bad happened!')
}

// `b` 函数调用 `c`
function b() {
    c()
}

// `a` 函数调用 `b`
function a() {
    b()
}

try {
    a() // 执行 `a` 函数
} catch (err) {
    // 判断所抛出的错误是否为 `Error` 的子类实例
    if (err instanceof Error) {
        console.log('Capture the error:')
        console.log(err.stack) // 打印堆栈追踪信息
        console.log(err instanceof CustomError, err instanceof Error) // 错误是否为(或继承自)CustomError 和 Error 类型
        console.log(err.constructor.name) // 自定义错误的构造器名称
    }
}
复制代码

对比ES 5/6 两种自定义错误的方式,运行结果均为:

Capture the error:
CustomError: something bad happened!
    at c (/Users/xavier/Documents/demos/javascript-demo/test.js:19:8)
    at b (/Users/xavier/Documents/demos/javascript-demo/test.js:23:2)
    at a (/Users/xavier/Documents/demos/javascript-demo/test.js:27:2)
    at Object.<anonymous> (/Users/xavier/Documents/demos/javascript-demo/test.js:31:2)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
true true
CustomError
复制代码

测试说明两种自定义错误的方式效果相同, ES6 class 写法虽然方便,但只是语法糖, ES5 的写法有利于我们理解 JavaScript 基于原型的继承方式,两者各有利弊。


以上所述就是小编给大家介绍的《ES5 / ES6 自定义错误类型比较》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Big Java Late Objects

Big Java Late Objects

Horstmann, Cay S. / 2012-2 / 896.00元

The introductory programming course is difficult. Many students fail to succeed or have trouble in the course because they don't understand the material and do not practice programming sufficiently. ......一起来看看 《Big Java Late Objects》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器