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

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

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

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


当前回答

更新代码,将原型分配给Error。Prototype和instanceof以及你的断言工作。

function NotImplementedError(message = "") {
    this.name = "NotImplementedError";
    this.message = message;
}
NotImplementedError.prototype = Error.prototype;

不过,我会抛出你自己的对象并检查name属性。

throw {name : "NotImplementedError", message : "too lazy to implement"}; 

根据评论进行编辑

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

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); }

控制台输出如下。

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()的行号,而不是抛出e发生的地方。然而,这可能比NotImplementedError.prototype.name = "NotImplementedError"行影响Error对象的副作用要好。

另外,注意NotImplementedError2,当我没有显式地设置.name时,它等于“Error”。然而,正如评论中提到的,因为该版本将prototype设置为new Error(),所以我可以设置NotImplementedError2.prototype.name = "NotImplementedError2"并OK。

其他回答

MDN有一个很好的例子:

try {
  throw new Error('Whoops!');
} catch (e) {
  console.log(e.name + ': ' + e.message);
}

我喜欢这样做:

利用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'); }

尝试为用户定义的错误类型的每个实例创建一个新的原型对象。它允许instanceof检查像往常一样运行,并且在Firefox和V8 (Chome, nodejs)中正确报告类型和消息。

function NotImplementedError(message){
    if(NotImplementedError.innercall===undefined){
        NotImplementedError.innercall = true;
        NotImplementedError.prototype = new Error(message);
        NotImplementedError.prototype.name = "NotImplementedError";
        NotImplementedError.prototype.constructor = NotImplementedError;

        return new NotImplementedError(message);
    }
    delete NotImplementedError.innercall;
}

注意,一个额外的条目将在正确的堆栈之前。

如果你使用Node/Chrome。下面的代码片段将为您提供满足以下要求的扩展。

err instanceof Error err instanceof CustomErrorType console.log() returns [CustomErrorType] when created with a message console.log() returns [CustomErrorType: message] when created without a message throw/stack provides the information at the point the error was created. Works optimally in Node.JS, and Chrome. Will pass instanceof checks in Chrome, Safari, Firefox and IE 8+, but will not have a valid stack outside of Chrome/Safari. I'm OK with that because I can debug in chrome, but code which requires specific error types will still function cross browser. If you need Node only you can easily remove the if statements and you're good to go.

片段

var CustomErrorType = function(message) {
    if (Object.defineProperty) {
        Object.defineProperty(this, "message", {
            value : message || "",
            enumerable : false
        });
    } else {
        this.message = message;
    }

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

CustomErrorType.prototype = new Error();
CustomErrorType.prototype.name = "CustomErrorType";

使用

var err = new CustomErrorType("foo");

输出

var err = new CustomErrorType("foo");
console.log(err);
console.log(err.stack);

[CustomErrorType: foo]
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

/errorTest.js:30
        throw err;
              ^
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3
function InvalidValueError(value, type) {
    this.message = "Expected `" + type.name + "`: " + value;
    var error = new Error(this.message);
    this.stack = error.stack;
}
InvalidValueError.prototype = new Error();
InvalidValueError.prototype.name = InvalidValueError.name;
InvalidValueError.prototype.constructor = InvalidValueError;