Is message property on Error propertyIsEnumerable?
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.
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
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
The correct result is false because the message
property of Error
is inherited (I think from the prototype).
精彩评论