开发者

Is message property on Error propertyIsEnumerable?

开发者 https://www.devze.com 2023-04-08 00:03 出处:网络
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.

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).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号