出于某种原因,在下面的代码段中,构造函数委托似乎不起作用:

function NotImplementedError() { 
  Error.apply(this, arguments); 
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")

运行该命令得到的消息是:"。有什么想法,为什么,或者是否有更好的方法来创建一个新的错误子类?是否有一个问题,应用到本机错误构造函数,我不知道?


当前回答

如果有人想知道如何创建一个自定义错误并获得堆栈跟踪:

function CustomError(message) {
  this.name = 'CustomError';
  this.message = message || '';
  var error = new Error(this.message);
  error.name = this.name;
  this.stack = error.stack;
}
CustomError.prototype = Object.create(Error.prototype);

try {
  throw new CustomError('foobar');
}
catch (e) {
  console.log('name:', e.name);
  console.log('message:', e.message);
  console.log('stack:', e.stack);
}

其他回答

构造函数需要类似于工厂方法,并返回您想要的内容。如果你需要额外的方法/属性,你可以在返回之前将它们添加到对象中。

function NotImplementedError(message) { return new Error("Not implemented", message); }

x = new NotImplementedError();

不过我不明白你为什么要这么做。为什么不直接使用new Error…? 自定义异常在JavaScript(或任何非类型化语言)中并没有真正添加太多内容。

上面的很多方法都不起作用。

最后一个是一个实际的错误。如果您使用字符串,它看起来很好,但它不会提供堆栈跟踪。如果你抛出错误,你不能有“Uncaught BadError: bad”,所以你必须删除自定义错误(遗憾的是)。如果你抛出一个对象,它看起来有点偏离,最后一个只是一个平均错误。

此方法创建一个具有自定义名称的错误,同时保留堆栈跟踪:

var errProto = Object.create(Error.prototype, { constructor: { value: Error, enumerable: false, writable: true, configurable: true } }) var isFirefox = !!window.InstallTrigger // Hide stack for Firefox only, as stacks can cause problems with high "frame" counts. function createError(name, message, hideStack) { if (message == null) { message = "" } var customError = Error(message) customError.name = name Object.setPrototypeOf(customError, errProto) if (isFirefox && hideStack) { customError.stack = "" } else if (isFirefox) { var stack = customError.stack var newline = stack.indexOf("\n") + 1 stack = stack.slice(newline) customError.stack = stack var split = stack.split(":") if (split.length > 4) { var a = split[3] var b = split[4] var t = b.slice(0, b.indexOf("\n")) customError.lineNumber = Number(a) customError.columnNumber = Number(t) } } else { var stack = customError.stack var split = stack.split("\n") var secondPart = split.slice(2).join("\n") stack = split[0] + "\n" + secondPart customError.stack = stack var split = secondPart.split(":") var a = split[2] var b = split[3] } throw customError } var frame = 0 function aFunction() { if (++frame === 100) { createError("LazyError", "function getting lazy", false, true) } else { requestAnimationFrame(aFunction) } } setTimeout(aFunction, Math.random() * 500) * { font-family: Verdana; } Check your inspector!

我喜欢这样做:

利用name,使toString()抛出"{code}: {message}" 将相同的东西返回给super,这样在stacktrace中就会显示相同的内容 将代码附加到错误。在代码中检查/解析代码比检查消息(例如,您可能希望本地化消息)更好 将消息附加到错误。message作为error.toString()的替代

class AppException extends Error { constructor(code, message) { const fullMsg = message ? `${code}: ${message}` : code; super(fullMsg); this.name = code; this.code = code; this.message = fullMsg; } toString() { return this.message; } } // Just a code try { throw new AppException('FORBIDDEN'); } catch(e) { console.error(e); console.error(e.toString()); console.log(e.code === 'FORBIDDEN'); } // A code and a message try { throw new AppException('FORBIDDEN', 'You don\'t have access to this page'); } catch(e) { console.error(e); console.error(e.toString()); console.log(e.code === 'FORBIDDEN'); }

更简单的方法。你可以让你的对象从Error对象继承。 例子:

function NotImplementError(message)
{
    this.message = message;
    Error.call();
    Error.call(message);
} 

我们所做的是使用函数call()调用Error类的构造函数,因此基本上与在其他面向对象语言中实现类继承是一样的。

以上所有的答案都很糟糕,真的。即使是107个向上的那个!真正的答案在这里:

从Error对象继承- message属性在哪里?

TL; diana:

a .没有设置message的原因是Error是一个函数,它返回一个新的Error对象,并且不以任何方式操作它。

B.正确的方法是从构造函数返回apply的结果,以及以通常复杂的javascript方式设置原型:

function MyError() { var temp = Error.apply(this, arguments); temp.name = this.name = 'MyError'; this.message = temp.message; if(Object.defineProperty) { // getter for more optimizy goodness /*this.stack = */Object.defineProperty(this, 'stack', { get: function() { return temp.stack }, configurable: true // so you can change it if you want }) } else { this.stack = temp.stack } } //inherit prototype using ECMAScript 5 (IE 9+) MyError.prototype = Object.create(Error.prototype, { constructor: { value: MyError, writable: true, configurable: true } }); 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 ...> //for EMCAScript 4 or ealier (IE 8 or ealier), inherit prototype this way instead of above code: /* var IntermediateInheritor = function() {}; IntermediateInheritor.prototype = Error.prototype; MyError.prototype = new IntermediateInheritor(); */

您可能会使用一些技巧来枚举tmp Error的所有不可枚举属性来设置它们,而不是显式地只设置stack和message,但是ie<9不支持这种技巧