4

What is the correct way to define a custom error in JavaScript?

Searching through SO I've found about 6 different ways to define a custom error, but I'm unsure as to the (dis)advantages to each of them.

From my (limited) understanding of prototype inheritance in JavaScript, this code should be sufficient:

function CustomError(message) {
   this.name = "CustomError";
   this.message = message;
}
CustomError.prototype = Object.create(Error.prototype);
n0w
  • 85
  • 8
  • somewhat related here http://stackoverflow.com/questions/783818/how-do-i-create-a-custom-error-in-javascript – Netorica Nov 25 '14 at 02:34
  • that was the main SO question that confused me. the highest ranked answer lists two different ways for the custom error to inherit from the `Error` object, neither of which is using the `Object.create()` method. the other answers seem to be variations of this theme. – n0w Nov 25 '14 at 02:38
  • 1
    `Object.create` is merely a new way of doing `CustomError.prototype = new Error()` -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create – James Sumners Nov 25 '14 at 02:42
  • 1
    @n0w Related: [Benefits of using `Object.create` for inheritance](http://stackoverflow.com/questions/17392857/benefits-of-using-object-create-for-inheritance) – Jonathan Lonowski Nov 25 '14 at 02:53
  • See also http://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript – Matt Browne Nov 25 '14 at 02:59

4 Answers4

4

The simplest of course, and in my opinion, the best to use unless you need more complex error reporting/handling is this:

throw Error("ERROR: This is an error, do not be alarmed.")
Scott
  • 3,736
  • 2
  • 26
  • 44
2

Usually I just use throw new Error(...), but for custom errors I find the following code works pretty well and still gives you stack traces on V8, i.e. in Chrome and node.js (which you don't get just by calling Error.apply() as suggested in the other answer):

function CustomError(message) {
    // Creates the this.stack getter
    if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor)
    this.message = message;
}
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;
CustomError.prototype.name = 'CustomError';

For more info, see these links:

What's a good way to extend Error in JavaScript?

https://plus.google.com/+MalteUbl/posts/HPA9uYimrQg

Community
  • 1
  • 1
Matt Browne
  • 12,169
  • 4
  • 59
  • 75
  • thanks. this seems to work correctly while also defining `this.stack` where available. the only change i'll make in my own code is to also define `this.name` in the constructor. – n0w Nov 25 '14 at 05:23
  • Good suggestion; I've added that in (did it on the prototype since the name is the same for all instances, but it doesn't really matter). – Matt Browne Nov 26 '14 at 18:56
  • Note: for fuller compatibility with IE, a few other things are needed; see http://stackoverflow.com/a/8460753/560114. – Matt Browne Nov 26 '14 at 19:00
1

This script depicts all the possible mechanisms for creating and using custom errors in JavaScript.

Also to get a complete understanding, it's essential to have an understanding of prototypal inheritance and delegation in JavaScript. I wrote this article which explains it clearly. https://medium.com/@amarpreet.singh/javascript-and-inheritance-90672f53d53c

I hope this helps.

function add(x, y) {
      if (x && y) {
        return x + y;
      } else {
        /**
         * 
         * the error thrown will be instanceof Error class and InvalidArgsError also
         */
        throw new InvalidArgsError();
        // throw new Invalid_Args_Error(); 
      }
    }

    // Declare custom error using using Class
    class Invalid_Args_Error extends Error {
      constructor() {
        super("Invalid arguments");
        Error.captureStackTrace(this);
      }
    }

    // Declare custom error using Function
    function InvalidArgsError(message) {
      this.message = `Invalid arguments`;
      Error.captureStackTrace(this);
    }
    // does the same magic as extends keyword
    Object.setPrototypeOf(InvalidArgsError.prototype, Error.prototype);

    try{
      add(2)
    }catch(e){
      // true
      if(e instanceof Error){
        console.log(e)
      }
      // true
      if(e instanceof InvalidArgsError){
        console.log(e)
      }
    }
0
function CustomError() {
   var returned = Error.apply(this, arguments);
   this.name = "CustomError";
   this.message = returned.message;
}
CustomError.prototype = Object.create(Error.prototype);
//CustomError.prototype = new Error();

var nie = new CustomError("some message");

console.log(nie);
console.log(nie.name);
console.log(nie.message);
alessandrio
  • 4,282
  • 2
  • 29
  • 40