首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在JavaScript中创建自定义错误?

如何在JavaScript中创建自定义错误?
EN

Stack Overflow用户
提问于 2009-04-23 22:35:22
回答 23查看 213K关注 0票数 254

由于某些原因,构造函数委托在下面的代码片段中看起来不起作用:

代码语言:javascript
复制
function NotImplementedError() { 
  Error.apply(this, arguments); 
}
NotImplementedError.prototype = new Error();

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

运行此命令将生成The message is: ''。有什么想法可以解释为什么,或者有没有更好的方法来创建一个新的Error子类?apply到本机Error构造函数有没有我不知道的问题?

EN

回答 23

Stack Overflow用户

回答已采纳

发布于 2009-05-16 03:51:53

更新您的代码以将您的原型分配给Error.prototype和instanceof,并且您的断言可以工作。

代码语言:javascript
复制
function NotImplementedError(message = "") {
    this.name = "NotImplementedError";
    this.message = message;
}
NotImplementedError.prototype = Error.prototype;

但是,我只会抛出您自己的对象,并只检查name属性。

代码语言:javascript
复制
throw {name : "NotImplementedError", message : "too lazy to implement"}; 

基于注释的编辑

在看了评论并试图记住为什么我会将prototype分配给Error.prototype而不是Nicholas Zakas在他的article中所做的new Error()之后,我用以下代码创建了一个jsFiddle

代码语言:javascript
复制
function NotImplementedError(message = "") {
  this.name = "NotImplementedError";
  this.message = message;
}
NotImplementedError.prototype = Error.prototype;

function NotImplementedError2(message = "") {
  this.message = message;
}
NotImplementedError2.prototype = new Error();

try {
  var e = new NotImplementedError("NotImplementedError message");
  throw e;
} catch (ex1) {
  console.log(ex1.stack);
  console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
  console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
  console.log("ex1.name = " + ex1.name);
  console.log("ex1.message = " + ex1.message);
}

try {
  var e = new NotImplementedError2("NotImplementedError2 message");
  throw e;
} catch (ex1) {
  console.log(ex1.stack);
  console.log("ex1 instanceof NotImplementedError2 = " + (ex1 instanceof NotImplementedError2));
  console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
  console.log("ex1.name = " + ex1.name);
  console.log("ex1.message = " + ex1.message);
}

控制台输出是这样的。

代码语言:javascript
复制
undefined
ex1 instanceof NotImplementedError = true
ex1 instanceof Error = true
ex1.name = NotImplementedError
ex1.message = NotImplementedError message
Error
    at window.onload (http://fiddle.jshell.net/MwMEJ/show/:29:34)
ex1 instanceof NotImplementedError2 = true
ex1 instanceof Error = true
ex1.name = Error
ex1.message = NotImplementedError2 message

这证实了我遇到的“问题”是错误的堆栈属性是创建new Error()的行号,而不是throw e发生的位置。然而,这可能比具有影响错误对象的NotImplementedError.prototype.name = "NotImplementedError"线的副作用要好。

另外,请注意对于NotImplementedError2,当我没有显式设置错误时,它等于“.name”。但是,正如注释中所提到的,因为该版本将prototype设置为new Error(),所以我可以设置为NotImplementedError2.prototype.name = "NotImplementedError2",这样就可以了。

票数 229
EN

Stack Overflow用户

发布于 2013-07-27 05:12:06

上面所有的答案都是非常糟糕的--真的。即使是有107个ups的那个!真正的答案就在这里:

Inheriting from the Error object - where is the message property?

TL;DR:

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

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

代码语言: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错误的所有不可枚举属性来设置它们,而不是只显式设置stackmessage,但是ie<9不支持这种技巧

票数 90
EN

Stack Overflow用户

发布于 2017-06-15 00:09:57

在ES2015中,您可以使用class干净利落地完成此操作:

代码语言:javascript
复制
class NotImplemented extends Error {
  constructor(message = "", ...args) {
    super(message, ...args);
    this.message = message + " has not yet been implemented.";
  }
}

这不会修改全局Error原型,允许您自定义messagename和其他属性,并正确捕获堆栈。它的可读性也很好。

当然,如果您的代码将在较旧的浏览器上运行,则可能需要使用像babel这样的工具。

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

https://stackoverflow.com/questions/783818

复制
相关文章

相似问题

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