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

在Python中,通常会子类化Exception。

在JS中应该做什么?


当前回答

为了避免针对每种不同类型的错误的样板文件,我将一些解决方案的智慧结合到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';
});

其他回答

如果你不关心错误的性能,这是你能做的最小的

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

你可以不使用new只使用MyError(message)

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

在ES6:

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

Mohsen has a great answer above in ES6 that sets the name, but if you're using TypeScript or if you're living in the future where hopefully this proposal for public and private class fields has moved past stage 3 as a proposal and made it into stage 4 as part of ECMAScript/JavaScript then you might want to know this is then just a little bit shorter. Stage 3 is where browsers start implementing features, so if your browser supports it the code below just might work. (Tested in the new Edge browser v81 it seems to work fine). Be warned though this is an unstable feature at the moment and should be used cautiously and you should always check browser support on unstable features. This post is mainly for those future dwellers when browsers might support this. To check support check MDN and Can I use. It's currently got 66% support across the browser market which is getting there but not that great so if you really want to use it now and don't want to wait either use a transpiler like Babel or something like TypeScript.

类EOFError扩展错误{ name = " EOFError " } 抛出新的EOFError("Oops error ");

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

类NamelessEOFError扩展错误{} 抛出新的NamelessEOFError("Oops error ");

正如其他人所说,在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);
}

重要提示:这个答案来自2016年,现在可能已经过时了。JavaScript总体上,特别是Node.js进步了很多,现在提供了更多的语法可能性来实现相同的结果。下面的内容是出于历史原因而保留的,只是为了以防有人正在处理遗留的Node.js版本。


最初的回答:

为了完整起见——因为之前的回答都没有提到这个方法——如果你正在使用Node.js,不必关心浏览器兼容性,那么使用内置的util模块继承(官方文档在这里)就很容易达到预期的效果。

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

文件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方法,该方法在目标对象上创建了一个堆栈属性(在本例中,实例化了CustomError)。有关它如何工作的更多细节,请查看这里的文档。