Javascript 错误属性上的消息属性是否可枚举?

Javascript 错误属性上的消息属性是否可枚举?,javascript,firefox,google-chrome,ecmascript-5,Javascript,Firefox,Google Chrome,Ecmascript 5,下面的正确结果是什么?是否有ECMA标准对此进行了规定?我目前的Chrome14.0.835.186m认为false,Firefox3.6.22认为true (new Error()).propertyIsEnumerable("message") 这是非常恼人的,因为Chrome过去也认为是真的,现在我因为这个改变而破坏了代码 正确的结果是错误的,因为继承了Error的message属性(我认为是从原型继承的)。我在ECMAScript 5规范中找不到任何需要它的地方(并不意味着它不在那里)

下面的正确结果是什么?是否有ECMA标准对此进行了规定?我目前的Chrome14.0.835.186m认为
false
,Firefox3.6.22认为
true

(new Error()).propertyIsEnumerable("message")

这是非常恼人的,因为Chrome过去也认为
是真的
,现在我因为这个改变而破坏了代码

正确的结果是错误的,因为继承了
Error
message
属性(我认为是从原型继承的)。

我在
ECMAScript 5
规范中找不到任何需要它的地方(并不意味着它不在那里),但它看起来是可配置的,因此您可以这样做:

Object.defineProperty( Error.prototype,'message',{enumerable:true});

console.log( Error.prototype.propertyIsEnumerable('message') ); // true
或者这个:

var err = new Error('a message');

Object.defineProperty( err,'message',{enumerable:true});

console.log( err.propertyIsEnumerable("message") );  // true

propertyEnumerable
不会为“内置”返回true,例如:

Error.prototype.message
Array.prototype.length

可枚举属性是指ECMA 262第15.2.4.7节中定义的直接在对象本身上设置的属性,可下载

例如:

> 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
> for(var key in arr) { console.log(key); }
kudos
> for(var key in err) { console.log(key); }
Something
propertyEnumerable
方法用于确定在
for..in
循环中可以使用什么

例如:

> 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
> for(var key in arr) { console.log(key); }
kudos
> for(var key in err) { console.log(key); }
Something
您使用的是
propertyEnumerable
而不是
hasOwnProperty

> err.hasOwnProperty("message")
true
> arr.hasOwnProperty("length")
true
以下是一些其他示例:

我的假设是,这些浏览器之所以能够正常工作,是因为它们正在为符合ECMAScript 5的要求而升级

编辑:

如果需要包括不可枚举属性在内的所有属性,可以使用
Object.getOwnPropertyNames(obj)
。下面是一个将不可枚举属性复制到另一个对象的示例

> 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
var err=新错误(“某些消息”); >var copy={}; >Object.getOwnPropertyNames(err).forEach(函数(键){ …复制[键]=错误[键]; ... }); >抄袭
{stack:'Error:repl:1:11处的一些消息\n接口处。

我将使用第一个示例,这样所有
Error
对象都有一个可枚举属性。检查第15章的最后一段:“本子句中描述的所有其他属性都有属性
{[[Writable]]:true,[[enumerable]]:false,[[Configurable]]:true}
除非另有说明。“:-)@CMS:谢谢你指点我!我已经运行了一些测试,Chrome 14中有一个奇怪的行为。如果你
var err=new Error('the msg');
err
将有自己的属性
“message”
,它是不可枚举的。但是如果您随后使
Error.prototype.message
可枚举,则我们先前创建的
err
仍然显示
.propertyEnumerable('message')Ӫ//false
,但奇怪的是,它将包含在
err
的枚举中。无论如何,如果你感兴趣,我会把它放在一起。@ӪӪ:不客气。是的,这显然是个bug(它记得我IE@CMS:是的,看起来in语句中的
for包含原型可枚举
foo
,尽管它被本地不可枚举
foo
隐藏,但为了让事情更加混乱,它正在从不可枚举的语句中检索值。要向每个对象添加可枚举,请确保不,首先是本地可枚举,其次是原型(非阴影)可枚举,最后是阴影可枚举(显示它在
原型上),但它给出了隐藏它的属性的值。这是一个有趣的问题。我想看看您如何在
错误
对象上使用
propertyEnumerable
的用例或示例。代码实际上是试图从错误对象复制字段。谢谢,这终于有了一些意义。因此我无法使用`for..in``发现内置属性?我添加了一个简短的示例,说明如何使用
对象执行此操作。getOwnPropertyNames
。单独调用
对象。getOwnPropertyNames
将返回一个属性名称数组。我添加的部分枚举该数组并复制
错误的属性对象到一个新的非错误对象。您是对的,我没有意识到(对象中的var字段){}
是不同的,但它们是不同的。实际上,我对后者很感兴趣。它仍然不会通过
错误上的
消息
字段枚举。您指的是什么区别?
属性可枚举
如果包含传入属性的对象的类型是内置的,则返回false,就像同一属性w一样不应在for/in循环中枚举。不同之处在于,
propertyEnumerable
为通过原型继承的属性返回
false
,而该属性仍然可以枚举。例如:
function f(){this.x=1};function g(){};g.prototype=new f();var x=new g();for(var f in x){console.log(f)};x.属性可枚举(“x”)