Javascript 创建自定义错误:理解MDN示例
关于如何在JS中创建自定义错误的以下示例可以在MDN()上找到 我正在努力理解发生了什么(具体问题如下)Javascript 创建自定义错误:理解MDN示例,javascript,error-handling,Javascript,Error Handling,关于如何在JS中创建自定义错误的以下示例可以在MDN()上找到 我正在努力理解发生了什么(具体问题如下) 函数自定义错误(foo、消息、文件名、行号){ var实例=新错误(消息、文件名、行号); instance.foo=foo; setPrototypeOf(实例,Object.getPrototypeOf(this)); if(Error.captureStackTrace){ 错误。captureStackTrace(实例,CustomError); } 返回实例; } CustomE
函数自定义错误(foo、消息、文件名、行号){
var实例=新错误(消息、文件名、行号);
instance.foo=foo;
setPrototypeOf(实例,Object.getPrototypeOf(this));
if(Error.captureStackTrace){
错误。captureStackTrace(实例,CustomError);
}
返回实例;
}
CustomError.prototype=Object.create(Error.prototype{
建造商:{
值:错误,
可枚举:false,
可写:对,
可配置:true
}
});
if(Object.setPrototypeOf){
setPrototypeOf(CustomError,Error);
}否则{
CustomError.\uuuu proto\uuuu=错误;
}
试一试{
抛出新的CustomError('baz','bazMessage');
}捕获(e){
console.log(e.foo);//baz
console.log(e.message);//消息
}
CustomError
作为正常功能时,此
的值在其内部是未定义的
。但如果将其用作构造函数,则该
将引用当前实例。考虑到此
被传递到getPrototypeOf
,将其作为普通函数调用将抛出错误并中断代码。但如果CustomError
按如下方式执行,则情况相同:
function CustomError(){
if(!(this instanceof MyError)) return new CustomError();
}
try/catch
语句中用new
关键字调用了实例中
的原型设置为此
的原型此
引用了CustomError
的当前实例,因为它是通过new
调用的Error.captureStackTrace
(仅限afaik chrome和nodejs支持),因此它会在使用该函数之前检查该函数是否存在编辑部分
- 每当我们使用构造函数(new关键字)创建一个新对象时,它就会将prototype链接到
(至少具有Person.prototype
属性),而prototype又链接到object.prototypeconstructor
- prototype链接到
,因为个人。prototype
构造函数创建了它,而构造函数将新创建的对象链接到他们自己的prototype对象。是的,您可以更改个人
,而不影响Person.prototype
Object.prototype
Error()
是一只野兽。
当调用它的构造函数时,它只会忽略这个
,并创建一个新的错误对象。
通常,在初始化自己的修改之前,可以使用Error.call(this,…)
为其超类初始化新的子类实例。但是,如果出现错误,这将失败,因为您将返回一个初始化的新错误对象,而实际实例保持不变。Error()只会忽略它的this
,并始终创建一个新实例。
为了避免这种情况,必须创建一个新的错误,然后需要将其原型更改为自定义原型(从Error.prototype派生),并返回此实例,丢弃由初始新创建的实例,就像Error那样(因此我们必须在所有子类中复制错误的不良行为)
以下工作:
MyErrorr = function() { // Class MyError
var prototype = Object.create (Error.prototype, { name: {writable: false, enumerable: true, value: "MyError"}});
function MyError (reason, callee) {
if(reason instanceof MyError)
return new MyError(reason.message); // clone
// creating an Error is a bit tricky, as Error.call(this, message) behaves like new Error(message), creating a new instance
var instance = new Error(reason);
if(Error.captureStackTrace)
Error.captureStackTrace(instance, callee?callee:MyError); // exclude the callee or at least MyError() from the stack trace
var stack = instance.stack; // force creation of the stack output before the prototype is switched (else the formatting is different, no idea why)
if(Object.setPrototypeOf)
Object.setPrototypeOf(instance, prototype);
else
instance.__proto__ = prototype;
return instance;
};
prototype.constructor = ConversionError;
MyError.prototype = prototype;
return MyError;
}();
由于未使用“this”,因此可以使用和不使用new
(就像Error
)实例化MyError
但有一个问题:
所有现存的错误类型实际上都是同一错误类的实例,而不是错误的子类。至少在铬上。另外,有些函数是Error的一部分,而不是Error.prototype的一部分,因此它们在类中不可用(如captureStackTrace)。如果你克隆它们,可能会有用。第二个列表中的第四个和第五个是真的,但我无法理解你在第三个列表中的意思。谢谢Hikmat,我会花一些时间消化你写的内容,然后跟进任何问题。关于你的“编辑部分”,是的,我完全理解你。我只是想强调另外一个事实,构造函数
Male
和Female
可能都使用Person.prototype
作为它们的原型对象,但因为我们将Male.prototype
和Female.prototype
设置为链接到Person.prototype
的空对象prototype(使用Create.object()
),而不是直接将其设置为Person.prototype
,我们确保可以将原型更改为Male
,而不会影响Male
。我认为,如果我们在构造函数中返回一个对象,那么使用this
引用新创建的对象都会被忽略(即构造函数的工作方式与普通函数相同).这是错误的理解吗?如果您使用new
kewword调用函数,则该函数可以访问this
,而不管函数内部发生了什么。Hikmat,我已经对此进行了一些研究,似乎如果我们从构造函数返回对象,它就不再像您期望的构造函数那样工作了tor函数开始工作。与任何其他函数一样,它不会将this
分配给新对象,然后返回它,而是从return
语句返回对象。请参见:,以及:this: