Reputation: 4724
What is the correct result of the following? Do any of the ECMA standards specify this? My current Chrome 14.0.835.186m thinks false
and Firefox 3.6.22 thinks true
.
(new Error()).propertyIsEnumerable("message")
This is extra annoying because Chrome used to think true
as well, and now I have broken code because of this change.
Upvotes: 2
Views: 510
Reputation: 20357
propertyIsEnumerable
doesn't return true for 'built-ins' like:
Error.prototype.message
or Array.prototype.length
Enumerable properties are those set directly on the object itself as defined in section 15.2.4.7 of ECMA 262, which can be downloaded here
For example:
> var arr = [];
> arr.propertyIsEnumerable("length")
false
> arr.kudos = 55;
55
> arr.propertyIsEnumerable("kudos")
true
> var err = new Error("some message");
> err.propertyIsEnumerable("message")
false
> err.Something = { };
{}
> err.propertyIsEnumerable("Something")
true
the propertyIsEnumerable
method is meant to determine what can be used in a for..in
loop.
For example:
> for(var key in arr) { console.log(key); }
kudos
> for(var key in err) { console.log(key); }
Something
Are you using propertyIsEnumerable
instead of hasOwnProperty
?
> err.hasOwnProperty("message")
true
> arr.hasOwnProperty("length")
true
Here are some other examples: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable
My assumption for the reason these used to work is that these browsers are ramping up for ECMAScript 5 compliance.
Edit:
If you need all properties including non-enumerable properties, you can use Object.getOwnPropertyNames(obj)
. Here's an example that copies non-enumerable properties to another object.
> var err = new Error("Some message");
> var copy = { };
> Object.getOwnPropertyNames(err).forEach(function(key) {
... copy[key] = err[key];
... });
> copy
{ stack: 'Error: Some message\n at repl:1:11\n at Interface.<anonymous> (r
epl.js:168:22)\n at Interface.emit (events.js:67:17)\n at Interface._onLin
e (readline.js:153:10)\n at Interface._line (readline.js:408:8)\n at Inter
face._ttyWrite (readline.js:585:14)\n at ReadStream.<anonymous> (readline.js:
73:12)\n at ReadStream.emit (events.js:70:17)\n at onKeypress (tty_win32.j
s:46:10)',
message: 'Some message',
arguments: undefined,
type: undefined }
> copy instanceof Error
false
> err instanceof Error
true
See here: https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects#section_2
Upvotes: 1
Reputation: 322572
I can't find in the ECMAScript 5
spec where it is required either way (doesn't mean it isn't there), but it does appear to be configurable, so you can do this:
Object.defineProperty( Error.prototype,'message',{enumerable:true});
console.log( Error.prototype.propertyIsEnumerable('message') ); // true
or this:
var err = new Error('a message');
Object.defineProperty( err,'message',{enumerable:true});
console.log( err.propertyIsEnumerable("message") ); // true
Upvotes: 2
Reputation: 693
The correct result is false because the message
property of Error
is inherited (I think from the prototype).
Upvotes: 0