Here is a simple answer that respects this contract:
- The stack trace is preserved
- The console error message retains the correct custom exception name and error message
Since JavaScript Exceptions are difficult to sub-class, I don't sub-class. I just create a new Exception typeclass and throw a regularuse an Error inside of it. I change the Error.name property so that it looks like my custom exception on the console:
var InvalidInputError = function(message) {
var error = new Error(message);
error.name = 'InvalidInputError';
return error;
};
The above new exception can be thrown just like a regular Error and it will work as expected, for example:
throw new InvalidInputError("Input must be a string");
// Output: Uncaught InvalidInputError: Input must be a string
Caveat: the stack trace is not perfect, as it will bring you to where the new Error is created and not where you throw. This is not a big deal on Chrome because it provides you with a full stack trace directly in the console. But it's more problematic on Firefox, for example.