Search code examples
javascriptnode.jserror-handlingprototypal-inheritancejavascript-inheritance

The `message` field value is not set in `CustomError` class in NodeJS with the classical inheritance through the function-constructor


This case works just fine:

class CustomError2015 extends Error {
    constructor(message) {
        super(message); // here the message is set correctly
        console.log("Message: " + this.message); 
    }
}

throw new CustomError2015("ECMAScript 2015 class inheritance");

I expected that this one would work the same way, but it didn't:

function CustomError(message){
    Error.call(this, message); // here the message IS NOT set
    console.log("Message: " + this.message); 
}
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;

throw new CustomError("CustomError function-like inheritance");

I'm wondering why? I there something wrong with my code or what?

* These code samples' playground.


Solution

  • Built in types (Error, Array) are exotic, that means that their constructor is not normal, and the objects of their instance are not normal, they are special internal objects. Therefore this:

      Error.call(this, message)
    

    does not work as Error has to return an exotic object, while this is a regular object, and the engine can't convert one into the other. Therefore it returns a new exotic error (which you ignore in your code):

      let exotic = Error.call(this);
      exotic === this // false
    

    The message gets set on that exotic object, and not on this.

    That works in classes as super(....) gets called before you can access this, and therefore this can be the exotic object, you cannot replicate that behaviour without classes.

    read on