4

I tried to extend the JavaScript error properties through the extension of the prototype of the Error constructor:

<script type="text/javascript">
// extending the Error properties to all the ones available in the various browsers:
Error.prototype = {
    name: null, // (all browsers); the name of the error
    message: null, // (all browsers); the error message as a string
    description: null, // (Internet Explorer); description of the error
    fileName: null, // (Firefox); the name of the file where the error occurred
    lineNumber: null, // (Firefox); the number of line where the error occurred
    columnNumber: null, // (Firefox); the number of column where the error occurred
    number: null, // (Internet Explorer); the error code as a number
    stack: null // (Firefox, Chrome); detailed information about the location where the error exactly occurred
};

function log(error) {
    var errors = [];

    for (var prop in error) {
        errors.push(prop + ': ' + error[prop]);
    }

    alert(errors.join('\n'));
}
</script>

Then I test the log function:

<script type="text/javascript>
try {
    var a = b; // b is undefined!
} catch(error) {
    log(error);
}
</script>

The result is that the error object only shows some properties (e.g. on Firefox fileName, lineNumber and columnNumber) like if it has not been extended.

But the most strange thing is that the for...in cycle seems unable to walk all the error object properties: trying to alert the standard property error.message normally returns a message.

So the results of my test are:

  1. the Error constructor is not extensible through its prototype, as other native constructors are;
  2. the for...in loop is not able to walk the properties of an error object.

Am I right?
Are there some interesting evidences/resources you may suggest to know more about it?

8
  • 1
    Error is a host object and therefore does not have to behave like "normal" JavaScript objects. Commented Jan 14, 2013 at 11:26
  • Mmh, interesting, I did not know about host objects. I am learning through something about through Stackoverflow threads. As for now, I understood they are special objects with special properties and behaviours, such as DOM objects, am I right?
    – yodabar
    Commented Jan 14, 2013 at 11:36
  • 3
    See es5.github.com/#x4.3.8. If you search for host object on this site you'll find some interesting statements about them. edit: They are basically objects supplied the environment and not part of the specification (just like DOM objects, yes). But the problem is probably just that Error.prototype is not writable (at least in Firefox). var obj = {foo: 'bar'}; Error.prototype = obj; Error.prototype == obj; results in false. Commented Jan 14, 2013 at 11:39
  • 1
    Even non host objects may have non enumerable properties, btw. Commented Jan 14, 2013 at 11:39
  • 2
    @Emanuele: You only have control over properties you create. Commented Jan 14, 2013 at 13:25

1 Answer 1

1

A. Like, Raynos said, The reason message isn't being set is that Error is a function that returns a new Error object and does not manipulate this in any way.

B. The way to do this right is to return the result of the apply from the constructor, as well as setting the prototype in the usual complicated javascripty way:

function MyError() {
    var tmp = Error.apply(this, arguments);
    tmp.name = this.name = 'MyError'

    this.stack = tmp.stack
    this.message = tmp.message

    return this
}
    var IntermediateInheritor = function() {}
        IntermediateInheritor.prototype = Error.prototype;
    MyError.prototype = new IntermediateInheritor()

var myError = new MyError("message");
console.log("The message is: '"+myError.message+"'") // The message is: 'message'
console.log(myError instanceof Error)                // true
console.log(myError instanceof MyError)              // true
console.log(myError.toString())                      // MyError: message
console.log(myError.stack)                           // MyError: message \n 
                                                     // <stack trace ...>

The only problems with this way of doing it at this point (i've iteratted it a bit) are that

  • properties other than stack and message aren't included in MyError and
  • the stacktrace has an additional line that isn't really necessary.

The first problem could be fixed by iterating through all the non-enumerable properties of error using the trick in this answer: Is it possible to get the non-enumerable inherited property names of an object?, but this isn't supported by ie<9. The second problem could be solved by tearing out that line in the stack trace, but I'm not sure how to safely do that (maybe just removing the second line of e.stack.toString() ??).

Not the answer you're looking for? Browse other questions tagged or ask your own question.