1

I have an custom error object that is extending the Error object:

function GTError(reason, loglevel, meta) {
    winston.log(loglevel, reason, meta);
    GTError.super_.apply(this, arguments);
}

util.inherits(GTError, Error);

I know that this doesn't work, and this question has workarounds for that. My question isn't how to work around it, my question is why doesn't it work? Why does calling GTError.super_.apply(this, arguments); (where GTError.super_ is Error) not populate the message property of the this?

enter image description here

can you explain, please? Thanks

4
  • You'll have to show the code for util.inherits or if it's from a library, tell which one. Commented Oct 30, 2016 at 8:19
  • @JJJ nodejs.org/api/… Commented Oct 30, 2016 at 8:20
  • What is GTError.super_? Commented Oct 30, 2016 at 8:23
  • 1
    @JosephtheDreamer: See robertklep's link above. Commented Oct 30, 2016 at 8:24

1 Answer 1

1

My question isn't how to work around it, my question is why doesn't it work?

Because the Error function always returns a new instance, even if you don't call it with new; it doesn't modify the object this refers to when you call it. From the ES5 specification:

When Error is called as a function rather than as a constructor, it creates and initialises a new Error object. Thus the function call Error(…) is equivalent to the object creation expression new Error(…) with the same arguments.

So in your code, GTError.super_.apply(this, arguments); (where GTError.super_ is Error) is effectively a no-op, because it creates and throws away an Error object rather than making Error populate the object passed as this. In fact, there's no way (in ES5) to make Error populate the object created by new in your new GTError expression, because of the way Error was defined.

The TC-39 committee fixed that in ES2015, but only when you're using the new class stuff (in order to maintain backward compatibility).


I know you said you just wanted to know why, but for others: In ES2015 and later, you can correctly subclass Error via the new class stuff. This syntax is supported in at least Node v4 in strict mode, and universally in Node v6. The following will work in any recent version of Chrome or Firefox:

let winston = {
  log: function(...args) {
    console.log("log", ...args);
  }
};
class GTError extends Error {
    constructor(reason, loglevel, meta) {
        winston.log(loglevel, reason, meta);
        super(reason, loglevel, meta);
    }
}
try {
  throw new GTError("reason", 10, "meta");
}
catch (e) {
  console.log(e instanceof Error);
  console.log(e instanceof GTError);
  console.log(e.message);
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.