Javascript 错误属性上的消息属性是否可枚举?
下面的正确结果是什么?是否有ECMA标准对此进行了规定?我目前的Chrome14.0.835.186m认为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规范中找不到任何需要它的地方(并不意味着它不在那里)
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”)