下面的示例说明如何在JS中创建自定义错误,可以在MDN (链接)上找到。
我很难理解到底发生了什么(下面是一些具体的问题)。
function CustomError(foo, message, fileName, lineNumber) {
var instance = new Error(message, fileName, lineNumber);
instance.foo = foo;
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, CustomError);
}
return instance;
}
CustomError.prototype = Object.create(Error.prototype, {
constructor: {
value: Error,
enumerable: false,
writable: true,
configurable: true
}
});
if (Object.setPrototypeOf) {
Object.setPrototypeOf(CustomError, Error);
} else {
CustomError.__proto__ = Error;
}
try {
throw new CustomError('baz', 'bazMessage');
} catch (e) {
console.log(e.foo); //baz
console.log(e.message); //bazMessage
}
问题
CustomError中返回一个对象,那么使用它作为构造函数(new CustomError())和将它用作普通函数对象(CustomError())会产生相同的结果吗?CustomError.prototype设置为Error.prototype,这样我们就可以扩展原型而不影响所有其他Error对象?prototype属性(Ref)。问题1)?Error instance设置为任何称为函数的函数,对吗?我不明白目的是什么/ this值将是什么。captureStackTrace检查的目的是什么?谢谢你帮我分析和理解这个片段。
编辑:
我想补充一点,我想我明白以下几点:
new关键字)创建一个新对象时,它就得到原型--链接到一个空对象,而该对象又是与Object.prototype链接的原型。Object.prototype,因为这样我们就可以扩展新对象的原型,而不需要改变它的原型链上所有带有Object.prototype的对象的行为。prototype属性,那么它应该反映相同的行为。实际上,我们应该将prototype属性设置为一个空对象,该对象反过来又是与我们新引入的“父”链接的原型。示例:
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
function Male(name) {
Person.call(this, name, "male");
}
Male.prototype = Object.create(Person.prototype, {
constructor: {
value: Male,
enumerable: false,
writeable: true
}
});
var person1 = new Male("Chris");
prototype属性时,我们不仅应该将一个新的空对象分配给prototype属性,还应该设置该空对象的constructor属性。Object.prototype的行为,其中constructor属性是Object (与其他内置的相同)。这应该可以解释第二个街区。我正确地理解了那个部分吗?
发布于 2018-07-08 23:12:02
CustomError作为正常函数时,this的值是它内部的undefined。但是,如果它被用作构造函数,this将引用当前实例。考虑到this被传递给getPrototypeOf,将其作为普通函数调用将引发错误并破坏代码。但是,如果CustomError像下面这样被改进的话,情况也是一样的:
函数CustomError(){ if(!(MyError的这个实例))返回新的CustomError();}new语句中用try/catch关键字调用了。instance的prototype被设置为this的原型。this是指CustomError的当前实例,因为它是通过new调用的。Error.captureStackTrace (afaik只支持chrome,nodejs支持它),所以在使用它之前它会检查函数是否存在。编辑部件
Person.prototype (至少有consctructor属性),而后者又是与Object.prototype链接的原型。Person.prototype,链接的原型,因为Person构造函数创建了它,而构造函数将新创建的对象链接到自己的原型对象。是的,您可以在不影响Person.prototype的情况下更改Object.prototype。发布于 2020-05-13 09:53:57
Error()是一只野兽。当调用其构造函数时,它只会忽略this并创建一个新的错误对象。通常,在初始化自己的修改之前,可以使用Error.call(this,...)来为其超类初始化新的子类实例。但是,如果出现错误,这将失败,因为您将得到一个初始化的新错误对象,并且实际实例保持不变。Error()简单地忽略它的this,并且总是创建一个新实例。为了避免这种情况,必须创建一个新的错误,然后需要将其原型更改为自定义原型(派生自Error.prototype),然后返回该实例,并丢弃由初始new创建的实例,就像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实例化MyError,也可以不使用new实例化(就像Error)
但是有一个问题:所有存在的错误类型实际上都是同一个错误类的实例,而不是错误的子类。至少在Chrome上。另外,有些函数是错误的一部分,而不是Error.prototype的一部分,因此它们在类中不可用(比如captureStackTrace)。也许如果你克隆他们的话就行了。
https://stackoverflow.com/questions/51234933
复制相似问题