javascriptexception

How do I create a custom Error in JavaScript?


For some reason it looks like constructor delegation doesn't work in the following snippet:

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

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

Running this gives The message is: ''. Any ideas as to why, or if there is a better way to create a new Error subclass? Is there a problem with applying to the native Error constructor that I don't know about?


Solution

  • Update your code to assign your prototype to the Error.prototype and the instanceof and your asserts work.

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

    However, I would just throw your own object and just check the name property.

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

    Edit based on comments

    After looking at the comments and trying to remember why I would assign prototype to Error.prototype instead of new Error() like Nicholas Zakas did in his article, I created a jsFiddle with the code below:

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

    The console output was this.

    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
    

    This confirmes the "problem" I ran into was the stack property of the error was the line number where new Error() was created, and not where the throw e occurred. However, that may be better that having the side effect of a NotImplementedError.prototype.name = "NotImplementedError" line affecting the Error object.

    Also, notice with NotImplementedError2, when I don't set the .name explicitly, it is equal to "Error". However, as mentioned in the comments, because that version sets prototype to new Error(), I could set NotImplementedError2.prototype.name = "NotImplementedError2" and be OK.