Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending JavaScript errors / exceptions

I was developing a small JS library and was to use there custom Error exceptions.

So, I decided to inherit them (ORLY?) from native Javascript Error object in this way:

var MyError = function(){
    Error.prototype.constructor.apply(this, arguments);
};

// Inherit without instantiating Error
var Surrogate = function(){};
Surrogate.prototype = Error.prototype;
MyError.prototype = new Surrogate();

// Add some original methods
MyError.prototype.uniqueMethod = function(){...}

Looks like usual inheritance.. But!

var err = new MyError("hello! this is text!");
console.log(err.message); // is giving me empty string!

I have read articles about this here and on MDN, but all of them saying me to use something like this:

var MyError = function(msg){
    this.message = msg;
};

But my question is - if not in the constructor of Error, then where message is initialized? May be somebody knows how Error native constructor works?

Thanks!

P.S. If it interesting - I was developing Enum.js library.

like image 347
Sergey Kamardin Avatar asked Jul 08 '13 15:07

Sergey Kamardin


People also ask

Can you throw custom exception with error object?

While the majority of exceptions are implementations of the global Error class, any old object can be thrown. With this in mind, there are two ways to throw an exception: directly via an Error object, and through a custom object.

How do you throw a custom error?

In order to create custom exception, we need to extend Exception class that belongs to java.lang package. Consider the following example, where we create a custom exception named WrongFileNameException: public class WrongFileNameException extends Exception { public WrongFileNameException(String errorMessage) {

Should you throw errors in JS?

It's best to avoid throwing errors from inside a Promise, because they may not always be caught, depending on how the code that called them is structured. However it's good practice to return an error when rejecting a Promise, and you can return Error custom types just like any other Error.


1 Answers

What you're doing is fine. It's Error that's the problem.

On this line:

Error.prototype.constructor.apply(this, arguments);

...you're calling Error (indirectly) as a normal function call rather than as part of a new expression, and the defined behavior for Error when you call it as a non-constructor function is to create a new, blank Error and return it (rather than populating this).

Now, in the normal case, what you're doing with the prototype would make the standard check for whether it was called as a constructor (if (this instanceof Error)) work. Unfortunately, it doesn't seem to be doing that, and whatever check it uses to determine how it was called doesn't seem to be immediately amenable to what you're trying to do. Even this (which is just a test, not meant to be something you'd actually do):

MyError.prototype = Error.prototype; // You wouldn't normally do this, it's just a test

...didn't solve it.

This answer to another Stack Overflow question points to a possible workaround (basically, let Error create the object and then return that from MyError):

function MyError(message) {
    var e = new Error(message);
    // ...apply your enhancements to `e`
    return e;
}

Not amazingly satisfying as you'd have to put your extensions directly on the object rather than use the prototype chain, but if Error refusees to play ball, your options are a bit limited...

like image 96
T.J. Crowder Avatar answered Oct 26 '22 18:10

T.J. Crowder