在JavaScript中扩展Error的好方法是什么?

2020/09/29 18:01 · javascript ·  · 0评论

我想在我的JS代码中扔一些东西,我希望它们是Error的instanceof,但我也想让它们成为其他东西。

通常,在Python中,可以将Exception子类化。

在JS中适合做些什么?

message属性唯一的标准字段Error对象是(请参阅MDN或EcmaScript语言规范,第15.11节)其他所有内容都是特定于平台的。

Mosts环境设置stack属性,但fileNamelineNumber实际上是无用的继承使用。

因此,简约的方法是:

function MyError(message) {
    this.name = 'MyError';
    this.message = message;
    this.stack = (new Error()).stack;
}
MyError.prototype = new Error;  // <-- remove this if you do not 
                                //     want MyError to be instanceof Error

您可以嗅探堆栈,从堆栈中移出不需要的元素,并提取诸如fileName和lineNumber之类的信息,但是这样做需要有关当前正在运行JavaScript的平台的信息。大多数情况下都是不必要的-如果您确实需要,可以在事后检查中进行。

Safari是一个明显的例外。没有stack属性,但是有throw关键字集sourceURLline要抛出的对象的属性。这些事情肯定是正确的。

我使用的测试用例可以在这里找到:JavaScript自制的Error对象比较

在ES6中:

class MyError extends Error {
  constructor(message) {
    super(message);
    this.name = 'MyError';
  }
}

资源

简而言之:

  • 如果您使用的是不带转译器的ES6

    class CustomError extends Error { /* ... */}
    
  • 如果您使用的是Babel Transpiler

选项1:使用babel-plugin-transform-b​​uiltin-extend

选项2:自己动手(灵感来自同一图书馆)

    function CustomError(...args) {
      const instance = Reflect.construct(Error, args);
      Reflect.setPrototypeOf(instance, Reflect.getPrototypeOf(this));
      return instance;
    }
    CustomError.prototype = Object.create(Error.prototype, {
      constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    Reflect.setPrototypeOf(CustomError, Error);
  • 如果您使用的是纯ES5

    function CustomError(message, fileName, lineNumber) {
      var instance = new Error(message, fileName, lineNumber);
      Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
      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;
    }
    
  • 替代方法:使用Classtrophobic框架

说明:

为什么使用ES6和Babel扩展Error类是一个问题?

因为CustomError实例不再被这样识别。

class CustomError extends Error {}
console.log(new CustomError('test') instanceof Error);// true
console.log(new CustomError('test') instanceof CustomError);// false

事实上,从巴贝尔的官方文档,你不能扩展任何内置的JavaScript类DateArrayDOMError

问题在这里描述:

那么其他答案呢?

所有给出的答案都解决了该instanceof问题,但是您丢失了常规错误console.log

console.log(new CustomError('test'));
// output:
// CustomError {name: "MyError", message: "test", stack: "Error↵    at CustomError (<anonymous>:4:19)↵    at <anonymous>:1:5"}

而使用上述方法,不仅可以解决instanceof问题,还可以保留常规错误console.log

console.log(new CustomError('test'));
// output:
// Error: test
//     at CustomError (<anonymous>:2:32)
//     at <anonymous>:1:5

编辑:请阅读评论。事实证明,这仅在V8(Chrome / Node.JS)中有效。我的意图是提供一个跨浏览器解决方案,该解决方案在所有浏览器中均适用,并在支持的地方提供堆栈跟踪。

编辑:我做了这个社区Wiki,以便进行更多编辑。

V8(Chrome / Node.JS)的解决方案可在Firefox中运行,并且可以修改为在IE中大部分正常运行。(请参阅发布结束)

function UserError(message) {
  this.constructor.prototype.__proto__ = Error.prototype // Make this an instanceof Error.
  Error.call(this) // Does not seem necessary. Perhaps remove this line?
  Error.captureStackTrace(this, this.constructor) // Creates the this.stack getter
  this.name = this.constructor.name; // Used to cause messages like "UserError: message" instead of the default "Error: message"
  this.message = message; // Used to set the message
}

原始帖子“显示代码!”

精简版:

function UserError(message) {
  this.constructor.prototype.__proto__ = Error.prototype
  Error.captureStackTrace(this, this.constructor)
  this.name = this.constructor.name
  this.message = message
}

我保留this.constructor.prototype.__proto__ = Error.prototype在函数内部,以将所有代码保持在一起。但是,您也可以this.constructor使用UserError和进行替换它允许您将代码移动到函数外部,因此仅被调用一次。

如果您沿那条路线行驶,请确保在第一次投掷之前致电该行UserError

该警告不适用该功能,因为无论顺序如何,都首先创建功能。因此,您可以毫无问题地将函数移至文件末尾。

浏览器兼容性

可在Firefox和Chrome(和Node.JS)中运行,并兑现了所有承诺。

Internet Explorer在以下方面失败

  • 错误不必从头err.stack开始,因此“这不是我的错”。

  • Error.captureStackTrace(this, this.constructor) 不存在,所以您需要做其他类似的事情

    if(Error.captureStackTrace) // AKA if not IE
        Error.captureStackTrace(this, this.constructor)
    
  • toString当你继承子类时,不再存在Error因此,您还需要添加。

    else
        this.toString = function () { return this.name + ': ' + this.message }
    
  • IE不会考虑UserError到是instanceof Error,除非你运行下面你前一段时间throw UserError

    UserError.prototype = Error.prototype
    

为了避免出现每种不同类型的错误,我将一些解决方案的精髓结合到一个  createErrorType函数中:

function createErrorType(name, init) {
  function E(message) {
    if (!Error.captureStackTrace)
      this.stack = (new Error()).stack;
    else
      Error.captureStackTrace(this, this.constructor);
    this.message = message;
    init && init.apply(this, arguments);
  }
  E.prototype = new Error();
  E.prototype.name = name;
  E.prototype.constructor = E;
  return E;
}

然后,您可以轻松定义新的错误类型,如下所示:

var NameError = createErrorType('NameError', function (name, invalidChar) {
  this.message = 'The name ' + name + ' may not contain ' + invalidChar;
});

var UnboundError = createErrorType('UnboundError', function (variableName) {
  this.message = 'Variable ' + variableName + ' is not bound';
});

2018年,我认为这是最好的方法; 支持IE9 +和现代浏览器。

更新:请参阅此测试和存储库,以比较不同的实现。

function CustomError(message) {
    Object.defineProperty(this, 'name', {
        enumerable: false,
        writable: false,
        value: 'CustomError'
    });

    Object.defineProperty(this, 'message', {
        enumerable: false,
        writable: true,
        value: message
    });

    if (Error.hasOwnProperty('captureStackTrace')) { // V8
        Error.captureStackTrace(this, CustomError);
    } else {
        Object.defineProperty(this, 'stack', {
            enumerable: false,
            writable: false,
            value: (new Error(message)).stack
        });
    }
}

if (typeof Object.setPrototypeOf === 'function') {
    Object.setPrototypeOf(CustomError.prototype, Error.prototype);
} else {
    CustomError.prototype = Object.create(Error.prototype, {
        constructor: { value: CustomError }
    });
}

还请注意,__proto__弃用属性,该属性在其他答案中广泛使用。

出于完整性的考虑(仅因为先前的答案中没有一个提到此方法),如果您使用的是Node.js,而不必关心浏览器的兼容性,则内置的效果很容易实现inheritsutil模块(此处为官方文档)。

例如,假设您要创建一个自定义错误类,该类将错误代码作为第一个参数,将错误消息作为第二个参数:

文件custom-error.js

'use strict';

var util = require('util');

function CustomError(code, message) {
  Error.captureStackTrace(this, CustomError);
  this.name = CustomError.name;
  this.code = code;
  this.message = message;
}

util.inherits(CustomError, Error);

module.exports = CustomError;

现在您可以实例化和传递/抛出您的CustomError

var CustomError = require('./path/to/custom-error');

// pass as the first argument to your callback
callback(new CustomError(404, 'Not found!'));

// or, if you are working with try/catch, throw it
throw new CustomError(500, 'Server Error!');

请注意,使用此代码段,堆栈跟踪将具有正确的文件名和行,并且错误实例将具有正确的名称!

发生这种情况的原因是captureStackTrace方法的使用,该方法stack在目标对象上创建了一个属性(在这种情况下,CustomError实例化了该属性)。有关其工作原理的更多详细信息,请参见此处的文档

Crescent Fresh的答案极富争议,令人误解。尽管他的警告无效,但是他没有解决其他限制。

首先,Crescent的“注意事项”(Caveats :)段落中的推理没有任何意义。这种解释意味着与多个catch语句相比,编码“一堆if(一堆if(Error instanceof MyError)else ...)”在某种程度上是繁重的或冗长的。单个catch块中的多个instanceof语句与多个catch语句一样简洁-简洁简洁的代码,没有任何技巧。这是模拟Java出色的特定于可抛出子类型的错误处理的好方法。

WRT“显示未设置子类的message属性”,如果您使用正确构造的Error子类,则情况并非如此。要创建自己的ErrorX Error子类,只需复制以“ var MyError =”开头的代码块,将一个单词“ MyError”更改为“ ErrorX”。(如果要向子类添加自定义方法,请遵循示例文本)。

JavaScript错误子类的真正且重要的限制是,对于跟踪并报告堆栈跟踪和实例化位置的JavaScript实现或调试器(如FireFox),您自己的Error子类实现中的位置将被记录为类,而如果您使用直接错误,它将是您运行“新错误(...)”的位置。IE用户可能永远不会注意到,但是FF上的Fire Bug用户将在这些错误旁边看到无用的文件名和行号值报告,并且必须深入到元素#1的堆栈跟踪中才能找到真正的实例化位置。

正如某些人所说,使用ES6相当容易:

class CustomError extends Error { }

所以我在我的应用程序(Angular,Typescript)中尝试了一下,但是它没有用。一段时间后,我发现问题来自Typescript:O

参见https://github.com/Microsoft/TypeScript/issues/13965

这非常令人不安,因为如果您这样做:

class CustomError extends Error {}

try {
  throw new CustomError()
} catch(e) {
  if (e instanceof CustomError) {
    console.log('Custom error');
  } else {
    console.log('Basic error');
  }
}

在节点中或直接在浏览器中,它将显示: Custom error

尝试在Typescript操场上的项目中使用Typescript运行它,它将显示Basic error...

解决方案是执行以下操作:

class CustomError extends Error {
  // we have to do the following because of: https://github.com/Microsoft/TypeScript/issues/13965
  // otherwise we cannot use instanceof later to catch a given type
  public __proto__: Error;

  constructor(message?: string) {
    const trueProto = new.target.prototype;
    super(message);

    this.__proto__ = trueProto;
  }
}

这个解决方案怎么样?

而不是使用以下方法抛出自定义错误:

throw new MyError("Oops!");

您将包装Error对象(有点像Decorator):

throw new MyError(Error("Oops!"));

这样可以确保所有属性都是正确的,例如堆栈,fileName lineNumber等。

然后,您要做的就是复制属性或为它们定义getter。这是使用吸气剂(IE9)的示例:

function MyError(wrapped)
{
        this.wrapped = wrapped;
        this.wrapped.name = 'MyError';
}

function wrap(attr)
{
        Object.defineProperty(MyError.prototype, attr, {
                get: function()
                {
                        return this.wrapped[attr];
                }
        });
}

MyError.prototype = Object.create(Error.prototype);
MyError.prototype.constructor = MyError;

wrap('name');
wrap('message');
wrap('stack');
wrap('fileName');
wrap('lineNumber');
wrap('columnNumber');

MyError.prototype.toString = function()
{
        return this.wrapped.toString();
};

我的解决方案比提供的其他答案更简单,并且没有缺点。

它保留了Error原型链和Error的所有属性,而无需对其有特定的了解。它已经在Chrome,Firefox,Node和IE11中进行了测试。

唯一的限制是在调用堆栈顶部有一个额外的条目。但这很容易被忽略。

这是带有两个自定义参数的示例:

function CustomError(message, param1, param2) {
    var err = new Error(message);
    Object.setPrototypeOf(err, CustomError.prototype);

    err.param1 = param1;
    err.param2 = param2;

    return err;
}

CustomError.prototype = Object.create(
    Error.prototype,
    {name: {value: 'CustomError', enumerable: false}}
);

用法示例:

try {
    throw new CustomError('Something Unexpected Happened!', 1234, 'neat');
} catch (ex) {
    console.log(ex.name); //CustomError
    console.log(ex.message); //Something Unexpected Happened!
    console.log(ex.param1); //1234
    console.log(ex.param2); //neat
    console.log(ex.stack); //stacktrace
    console.log(ex instanceof Error); //true
    console.log(ex instanceof CustomError); //true
}

对于需要setPrototypeOf的polyfil的环境:

Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
    obj.__proto__ = proto;
    return obj;
};

在上面的示例中Error.apply(也Error.call)对我没有任何帮助(Firefox 3.6 / Chrome 5)。我使用的解决方法是:

function MyError(message, fileName, lineNumber) {
    var err = new Error();

    if (err.stack) {
        // remove one stack level:
        if (typeof(Components) != 'undefined') {
            // Mozilla:
            this.stack = err.stack.substring(err.stack.indexOf('\n')+1);
        }
        else if (typeof(chrome) != 'undefined' || typeof(process) != 'undefined') {
            // Google Chrome/Node.js:
            this.stack = err.stack.replace(/\n[^\n]*/,'');
        }
        else {
            this.stack = err.stack;
        }
    }
    this.message    = message    === undefined ? err.message    : message;
    this.fileName   = fileName   === undefined ? err.fileName   : fileName;
    this.lineNumber = lineNumber === undefined ? err.lineNumber : lineNumber;
}

MyError.prototype = new Error();
MyError.prototype.constructor = MyError;
MyError.prototype.name = 'MyError';

正如其他人所说,在Node中,它很简单:

class DumbError extends Error {
    constructor(foo = 'bar', ...params) {
        super(...params);

        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, DumbError);
        }

        this.name = 'DumbError';

        this.foo = foo;
        this.date = new Date();
    }
}

try {
    let x = 3;
    if (x < 10) {
        throw new DumbError();
    }
} catch (error) {
    console.log(error);
}

我只想补充别人已经说过的话:

为了确保自定义错误类在堆栈跟踪中正确显示,您需要将自定义错误类的原型的name属性设置为自定义错误类的name属性。这就是我的意思:

CustomError.prototype = Error.prototype;
CustomError.prototype.name = 'CustomError';

因此,完整的示例将是:

    var CustomError = function(message) {
        var err = new Error(message);
        err.name = 'CustomError';
        this.name = err.name;
        this.message = err.message;
        //check if there is a stack property supported in browser
        if (err.stack) {
            this.stack = err.stack;
        }
        //we should define how our toString function works as this will be used internally
        //by the browser's stack trace generation function
        this.toString = function() {
           return this.name + ': ' + this.message;
        };
    };
    CustomError.prototype = new Error();
    CustomError.prototype.name = 'CustomError';

一切都说完了之后,您就抛出了新的异常,它看起来像这样(我在chrome dev工具中偷懒地尝试过):

CustomError: Stuff Happened. GASP!
    at Error.CustomError (<anonymous>:3:19)
    at <anonymous>:2:7
    at Object.InjectedScript._evaluateOn (<anonymous>:603:39)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:562:52)
    at Object.InjectedScript.evaluate (<anonymous>:481:21)

我的2美分:

为什么还要另一个答案?

a)因为访问Error.stack属性(如在某些答案中)会带来很大的性能损失。

b)因为只有一行。

c)因为https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error的解决方案似乎并未保留堆栈信息。

//MyError class constructor
function MyError(msg){
    this.__proto__.__proto__ = Error.apply(null, arguments);
};

使用范例

http://jsfiddle.net/luciotato/xXyeB/

它有什么作用?

this.__proto__.__proto__MyError.prototype.__proto__,因此将__proto__MyError FOR ALL INSTANCES 设置为特定的新创建的Error。它保留MyError类的属性和方法,还将新的Error属性(包括.stack)放入__proto__链中。

明显的问题:

具有有用的堆栈信息的MyError实例不能超过一个。

如果您不完全了解,请不要使用此解决方案this.__proto__.__proto__=

由于很难对JavaScript异常进行子类化,因此我不对它进行子类化。我只是创建一个新的Exception类,并在其中使用Error。我更改了Error.name属性,使其看起来像我在控制台上的自定义异常:

var InvalidInputError = function(message) {
    var error = new Error(message);
    error.name = 'InvalidInputError';
    return error;
};

可以像常规错误一样抛出上面的新异常,并且它将按预期运行,例如:

throw new InvalidInputError("Input must be a string");
// Output: Uncaught InvalidInputError: Input must be a string 

警告:堆栈跟踪不是完美的,因为它将使您到达创建新错误的位置,而不是引发错误的位置。在Chrome上这不是什么大问题,因为它可以直接在控制台中为您提供完整的堆栈跟踪。但是,例如在Firefox上,问题就更多了。

正如Mohsen的答案所指出的那样,在ES6中可以使用类来扩展错误。这要容易得多,并且它们的行为与本机错误更加一致……但是,不幸的是,如果需要支持ES6之前的浏览器,在浏览器中使用它并不是一件容易的事。有关如何实施的一些说明,请参见下文,但与此同时,我建议一种相对简单的方法,该方法结合了其他答案中的一些最佳建议:

function CustomError(message) {
    //This is for future compatibility with the ES6 version, which
    //would display a similar message if invoked without the
    //`new` operator.
    if (!(this instanceof CustomError)) {
        throw new TypeError("Constructor 'CustomError' cannot be invoked without 'new'");
    }
    this.message = message;

    //Stack trace in V8
    if (Error.captureStackTrace) {
       Error.captureStackTrace(this, CustomError);
    }
    else this.stack = (new Error).stack;
}
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.name = 'CustomError';

在ES6中,它很简单:

class CustomError extends Error {}

...并且您可以使用来检测对ES6类的支持try {eval('class X{}'),但是如果尝试在旧版浏览器加载的脚本中包含ES6版本,则会收到语法错误。因此,支持所有浏览器的唯一方法是为eval()支持ES6的浏览器动态加载单独的脚本(例如,通过AJAX或)。更为复杂的是,eval()并非所有环境都支持(由于内容安全策略),这可能会或可能不会成为您项目的考虑因素。

因此,就目前而言,无论是上面的第一种方法,还是直接使用Error而不尝试扩展它,对于需要支持非ES6浏览器的代码,实际上似乎是最好的方法。

有些人可能要考虑另一种方法,即使用Object.setPrototypeOf()可用的位置创建一个错误对象,该对象是您的自定义错误类型的实例,但其外观和行为更像是控制台中的本机错误(感谢Ben的回答)的建议)。这是我对这种方法的看法:https : //gist.github.com/mbrowne/fe45db61cea7858d11be933a998926a8但是考虑到有一天我们将只能使用ES6,就我个人而言,我不确定这种方法的复杂性是否值得。

做到这一点的方法是从构造函数返回apply的结果,并以通常的复杂javascript方式设置原型:

function MyError() {
    var tmp = Error.apply(this, arguments);
    tmp.name = this.name = 'MyError'

    this.stack = tmp.stack
    this.message = tmp.message

    return this
}
    var IntermediateInheritor = function() {}
        IntermediateInheritor.prototype = Error.prototype;
    MyError.prototype = new IntermediateInheritor()

var myError = new MyError("message");
console.log("The message is: '"+myError.message+"'") // The message is: 'message'
console.log(myError instanceof Error)                // true
console.log(myError instanceof MyError)              // true
console.log(myError.toString())                      // MyError: message
console.log(myError.stack)                           // MyError: message \n 
                                                     // <stack trace ...>

在这种情况下(我已经对其进行了一些迭代),这样做的唯一问题是

  • stackmessage中不包含MyError和的其他属性
  • stacktrace还有另一行,这并不是真正必要的。

第一个问题可以通过使用此答案中的技巧遍历错误的所有不可枚举的属性来解决:是否可以获取对象的不可枚举的继承属性名称?,但是ie <9不支持此功能。第二个问题可以通过在堆栈跟踪中删除该行来解决,但是我不确定如何安全地执行此操作(也许只是删除e.stack.toString()的第二行)。

该代码段显示了所有内容。

function add(x, y) {
      if (x && y) {
        return x + y;
      } else {
        /**
         * 
         * the error thrown will be instanceof Error class and InvalidArgsError also
         */
        throw new InvalidArgsError();
        // throw new Invalid_Args_Error(); 
      }
    }

    // Declare custom error using using Class
    class Invalid_Args_Error extends Error {
      constructor() {
        super("Invalid arguments");
        Error.captureStackTrace(this);
      }
    }

    // Declare custom error using Function
    function InvalidArgsError(message) {
      this.message = `Invalid arguments`;
      Error.captureStackTrace(this);
    }
    // does the same magic as extends keyword
    Object.setPrototypeOf(InvalidArgsError.prototype, Error.prototype);

    try{
      add(2)
    }catch(e){
      // true
      if(e instanceof Error){
        console.log(e)
      }
      // true
      if(e instanceof InvalidArgsError){
        console.log(e)
      }
    }

Mohsen在ES6上面有一个很好的答案,它设置了名称,但是如果您使用的是TypeScript,或者您生活在未来,希望有关公共和私有类字段的提案已经超过了阶段3的提案,进入第4阶段(作为ECMAScript / JavaScript的一部分),那么您可能想知道它会短一些。第3阶段是浏览器开始实现功能的地方,因此,如果您的浏览器支持,则下面的代码可能会起作用。(在新的Edge浏览器v81中进行了测试,它似乎工作正常)。请注意,尽管此功能目前尚不稳定,应谨慎使用,并且应始终检查浏览器对不稳定功能的支持。这篇文章主要针对浏览器可能支持的那些将来的居民。要检查支持,请检查MDN我可以使用它目前有跨浏览器的市场这是越来越有,但不是很大,所以如果你真的想现在使用它,不想等待或者使用像transpiler 66%的支持巴别塔之类的东西打字稿

class EOFError extends Error { 
  name="EOFError"
}
throw new EOFError("Oops errored");

将此错误与无名错误进行比较,该错误在抛出时将不会记录其名称。

class NamelessEOFError extends Error {}
throw new NamelessEOFError("Oops errored");

我会退后一步,考虑您为什么要这样做?我认为关键是要以不同的方式处理不同的错误。

例如,在Python中,您可以将catch语句限制为仅catch MyValidationError,也许您希望能够在javascript中执行类似的操作。

catch (MyValidationError e) {
    ....
}

您无法在javascript中执行此操作。只会有一个捕获块。您应该对错误使用if语句来确定其类型。


catch(e) {
if(isMyValidationError(e)) {
...
} else {
// maybe rethrow?
throw e;
}
}

我想我会抛出一个带有类型,消息和您认为合适的其他属性的原始对象。

throw { type: "validation", message: "Invalid timestamp" }

当您发现错误时:

catch(e) {
    if(e.type === "validation") {
         // handle error
    }
    // re-throw, or whatever else
}

自定义错误装饰器

这是基于乔治·贝利(George Bailey)的回答,但扩展并简化了最初的想法。它是用CoffeeScript编写的,但是很容易转换为JavaScript。这个想法是通过使用包装它的装饰器扩展Bailey的自定义错误,使您可以轻松地创建新的自定义错误。

注意:这仅在V8中有效。Error.captureStackTrace在其他环境中不支持

定义

装饰器采用错误类型的名称,然后返回采用错误消息的函数并将其括起来。

CoreError = (@message) ->

    @constructor.prototype.__proto__ = Error.prototype
    Error.captureStackTrace @, @constructor
    @name = @constructor.name

BaseError = (type) ->

    (message) -> new CoreError "#{ type }Error: #{ message }"

现在,很容易创建新的错误类型。

StorageError   = BaseError "Storage"
SignatureError = BaseError "Signature"

为了好玩,您现在可以定义一个函数,SignatureError如果调用了太多的参数,则该函数将抛出a

f = -> throw SignatureError "too many args" if arguments.length

这已经过很好的测试,并且似乎可以在V8上完美运行,保持回溯,位置等。

注意:new构造自定义错误时,使用是可选的。

如果您不关心错误的表现,这是您可以做的最小的事情

Object.setPrototypeOf(MyError.prototype, Error.prototype)
function MyError(message) {
    const error = new Error(message)
    Object.setPrototypeOf(error, MyError.prototype);
    return error
}

您可以在没有新的MyError(message)的情况下使用它

通过在调用构造函数Error之后更改原型,我们不必设置调用堆栈和消息

本文地址:http://javascript.askforanswer.com/zaijavascriptzhongkuozhanerrordehaofangfashishenme.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!