首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建自定义错误:理解MDN示例

创建自定义错误:理解MDN示例
EN

Stack Overflow用户
提问于 2018-07-08 18:30:02
回答 2查看 1.1K关注 0票数 1

下面的示例说明如何在JS中创建自定义错误,可以在MDN (链接)上找到。

我很难理解到底发生了什么(下面是一些具体的问题)。

代码语言:javascript
复制
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
}

问题

  1. 既然我们在CustomError中返回一个对象,那么使用它作为构造函数(new CustomError())和将它用作普通函数对象(CustomError())会产生相同的结果吗?
  2. 在第11行:我们是否在这里创建了一个新对象,而不是直接将CustomError.prototype设置为Error.prototype,这样我们就可以扩展原型而不影响所有其他Error对象?
  3. 同样在第11行:如果不能将函数用作构造函数(ref ),为什么还要费心设置函数的prototype属性(Ref)。问题1)?
  4. 在第4行中,我们将Error instance设置为任何称为函数的函数,对吗?我不明白目的是什么/ this值将是什么。
  5. captureStackTrace检查的目的是什么?

谢谢你帮我分析和理解这个片段。

编辑:

我想补充一点,我想我明白以下几点:

  • 每当我们使用构造函数(new关键字)创建一个新对象时,它就得到原型--链接到一个空对象,而该对象又是与Object.prototype链接的原型。
  • 它是与一个新的空对象链接的原型,而不是直接链接到Object.prototype,因为这样我们就可以扩展新对象的原型,而不需要改变它的原型链上所有带有Object.prototype的对象的行为。
  • 如果我们有两个级别的“继承”,从而手动更改构造函数的prototype属性,那么它应该反映相同的行为。实际上,我们应该将prototype属性设置为一个空对象,该对象反过来又是与我们新引入的“父”链接的原型。

示例:

代码语言:javascript
复制
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 (与其他内置的相同)。

这应该可以解释第二个街区。我正确地理解了那个部分吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-08 23:12:02

  1. 当使用CustomError作为正常函数时,this的值是它内部的undefined。但是,如果它被用作构造函数,this将引用当前实例。考虑到this被传递给getPrototypeOf,将其作为普通函数调用将引发错误并破坏代码。但是,如果CustomError像下面这样被改进的话,情况也是一样的: 函数CustomError(){ if(!(MyError的这个实例))返回新的CustomError();}
  2. 就像你想的那样
  3. 我不知道为什么您认为它不能用作构造函数,因为它已经在new语句中用try/catch关键字调用了。
  4. 在第4行中,instance的prototype被设置为this的原型。this是指CustomError的当前实例,因为它是通过new调用的。
  5. 因为并非所有环境都支持Error.captureStackTrace (afaik只支持chrome,nodejs支持它),所以在使用它之前它会检查函数是否存在。

编辑部件

  • 每当我们创建一个带有构造函数(新关键字)的新对象时,它就得到原型--链接到Person.prototype (至少有consctructor属性),而后者又是与Object.prototype链接的原型。
  • 它是与Person.prototype,链接的原型,因为Person构造函数创建了它,而构造函数将新创建的对象链接到自己的原型对象。是的,您可以在不影响Person.prototype的情况下更改Object.prototype
票数 1
EN

Stack Overflow用户

发布于 2020-05-13 09:53:57

Error()是一只野兽。当调用其构造函数时,它只会忽略this并创建一个新的错误对象。通常,在初始化自己的修改之前,可以使用Error.call(this,...)来为其超类初始化新的子类实例。但是,如果出现错误,这将失败,因为您将得到一个初始化的新错误对象,并且实际实例保持不变。Error()简单地忽略它的this,并且总是创建一个新实例。为了避免这种情况,必须创建一个新的错误,然后需要将其原型更改为自定义原型(派生自Error.prototype),然后返回该实例,并丢弃由初始new创建的实例,就像Error做的那样(因此我们必须在所有子类中复制错误的错误行为)。

以下工作:

代码语言:javascript
复制
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)。也许如果你克隆他们的话就行了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51234933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档