问题描述
在开发中需要实现一个自定义Error,它继承自Error
,按照经验,一般会这样来做:
function CustomError(message) {
this.message = message;
}
CustomError.prototype = Object.create(Error.prototype, {
name: {
value: ‘customError‘
},
constructor: {
value: Error,
enumerable: false,
writable: true,
configurable: true
}
});
var myError = new CustomError(‘f**k error!‘);
console.log(myError instanceof CustomError) // true
console.log(myError instanceof Error) // true
它工作的很好,没有明显的bug,所以长期以来,我都这么干。直到某天试着这样:
> console.log(CustomError instanceof Error)
< false
为什么这里返回的是false
?认真思考,等下给出答案。
再一个,回到题目本身,我想和大家讨论的是函数之间的继承关系。具体而言,就是CustomError
通过原型链继承于Error
,实现预期不仅表现在CustomError
的每一个实例上,也表现在其本身——CustomError instanceof Error === true
解决之道
要解答上面的问题,必须清楚这里的instanceof
操作,就是判断CustomError
的原型链(proto)上是否存在Error.prototype
,返回一个Boolean。
所以结果false
并不令人感到奇怪,因为没有任何迹象表明CustomError.__proto__
指向Error.prototype
。
上面这句话暗含了解决之道:
> CustomError.__proto__ = Error.prototype
> CustomError instanceof Error
< true
延展
- 原型(prototype)
每个函数有一个prototype属性,它的值是一个对象(属性的集合),默认只有一个constructor属性。 - 原型链(proto)
1、每个对象默认有一个__proto__属性,指向创建该对象的函数的prototype。
2、函数也是对象,也默认有一个__proto__属性,指向Function.prototype。
3、访问一个对象的属性时,先在该对象的基本属性中查找,如果没有,在沿着__proto__这条链向上查找,这就是原型链。 - instanceof 运算符
用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。 - Object.create()
使用指定的原型对象及其属性去创建一个新的对象(依然维持着对原型对象的引用)。