javascriptexceptioncustom-exceptions

Throwing custom exceptions in Javascript. Which style to use?


Douglas Crockford recommends doing something like this:

throw {
    name: "System Error",
    message: "Something horrible happened."
};

But you could also do something like this:

function IllegalArgumentException(message) {
    this.message = message;
}

throw new IllegalArgumentException("Argument cannot be less than zero");

and then do:

try {
    //some code that generates exceptions
} catch(e) {    
    if(e instanceof IllegalArgumentException) {
        //handle this
    } else if(e instanceof SomeOtherTypeOfException) {
        //handle this
    }
}

I guess you could include a type property in Crockford's implementation and then examine that instead of doing an instanceof. Is there any advantage from doing one versus the other?


Solution

  • Update 2022

    If your environment supports ES6, you should use inheritance from Error class, as recommended by Mozilla:

    class IllegalArgumentException extends Error {
       // ...
    }
    

    This is also the most upvoted answer in What's a good way to extend Error in JavaScript?.


    Pre-ES6 (original answer)

    Also pre-ES6 environments provide the Error class as basis for exceptions. It already allows you to define a message, but also provides a useful stack property to track down the context of the exception. You can create your own exception type by using prototypical inheritance. There are already several stackoverflow discussions (for example: here), how to do this properly. However, I had to dig a little bit until I found the correct and modern approach. Please be aware that the approach that is suggested in the Mozilla documentation (see above) is not liked by the stackoverflow community. After a lot of reading I came out with that approach for inherit from Error.prototype:

    function IllegalArgumentException(sMessage) {
        this.name = "IllegalArgumentException";
        this.message = sMessage;
        this.stack = (new Error()).stack;
    }
    IllegalArgumentException.prototype = Object.create(Error.prototype);
    IllegalArgumentException.prototype.constructor = IllegalArgumentException;