如何枚举JavaScript对象的属性?
我实际上想要列出所有已定义的变量及其值,但我已经了解到定义变量实际上会创建窗口对象的属性.
很简单:
for(var propertyName in myObject) { // propertyName is what you want // you can get the value like this: myObject[propertyName] }
现在,您不会以这种方式获取私有变量,因为它们不可用.
编辑:@bitwiseplatypus是正确的,除非你使用该hasOwnProperty()
方法,你将获得继承的属性 - 但是,我不知道为什么熟悉面向对象编程的人会期望更少!通常情况下,提起这件事的人一直受到道格拉斯·克罗克福德(Douglas Crockford)关于此事的警告,这仍然让我感到困惑.同样,继承是OO语言的正常部分,因此它是JavaScript的一部分,尽管它是典型的.
现在,这么说,hasOwnProperty()
是用于过滤是有用的,但我们并不需要发出警告声,好像有什么东西在得到继承属性危险.
编辑2:@bitwiseplatypus提出了如果有人在您最初编写对象(通过其原型)之后的某个时间点向对象添加属性/方法时会发生的情况 - 尽管这可能会导致意外行为,我个人并不认为这完全是我的问题.只是一个意见问题.此外,如果我以这样的方式设计东西,即在构造我的对象期间使用原型,然后让代码迭代对象的属性并且我想要所有继承的属性,该怎么办?我不会用hasOwnProperty()
.然后,让我们说,有人稍后会添加新属性.如果那时事情表现不好,这是我的错吗?我不这么认为.我认为这就是为什么jQuery作为一个例子,已经指定了扩展其工作方式的方法(通过jQuery.extend
和jQuery.fn.extend
).
使用for..in
循环枚举对象的属性,但要小心.枚举将返回属性,不仅返回被枚举对象的属性,还返回任何父对象的原型.
var myObject = {foo: 'bar'}; for (var name in myObject) { alert(name); } // results in a single alert of 'foo' Object.prototype.baz = 'quux'; for (var name in myObject) { alert(name); } // results in two alerts, one for 'foo' and one for 'baz'
要避免在枚举中包含继承的属性,请检查hasOwnProperty()
:
for (var name in myObject) { if (myObject.hasOwnProperty(name)) { alert(name); } }
编辑:我不同意JasonBunting的声明,即我们不需要担心枚举继承的属性.还有就是在枚举了,你是不是希望继承属性,因为它可以改变你的代码的行为危险.
这个问题是否存在于其他语言中并不重要; 事实是它存在,并且JavaScript特别容易受到攻击,因为对对象原型的修改会影响子对象,即使在实例化之后进行修改也是如此.
这就是JavaScript提供的原因hasOwnProperty()
,这就是为什么你应该使用它来确保第三方代码(或任何其他可能修改原型的代码)不会破坏你的原因.除了添加一些额外的代码字节外,使用没有任何缺点hasOwnProperty()
.
已经多次提出的标准方法是:
for (var name in myObject) { alert(name); }
但是,Internet Explorer 6,7和8在JavaScript解释器中有一个错误,其效果是某些键未被枚举.如果您运行此代码:
var obj = { toString: 12}; for (var name in obj) { alert(name); }
如果在IE以外的所有浏览器中都会提示"12".IE将简单地忽略此密钥.受影响的键值为:
isPrototypeOf
hasOwnProperty
toLocaleString
toString
valueOf
要在IE中真正安全,你必须使用类似的东西:
for (var key in myObject) { alert(key); } var shadowedKeys = [ "isPrototypeOf", "hasOwnProperty", "toLocaleString", "toString", "valueOf" ]; for (var i=0, a=shadowedKeys, l=a.length; i好消息是EcmaScript 5定义了
Object.keys(myObject)
函数,它将对象的键作为数组返回,而某些浏览器(例如Safari 4)已经实现了它.
4> 小智..:在现代浏览器(ECMAScript 5)中,您可以执行以下所有可枚举属性:
Object.keys(obj) (检查链接以获取旧版浏览器向后兼容性的片段)
或者获得非可枚举的属性:
Object.getOwnPropertyNames(OBJ)
检查ECMAScript 5兼容性表
附加信息: 什么是可枚举属性?
如果要处理某种类型的Error对象(例如TypeError),则需要使用Object.getOwnPropertyNames(obj),因为这些属性不可枚举。
5> 小智..:我认为令我感到意外的一个例子是相关的:
var myObject = { name: "Cody", status: "Surprised" }; for (var propertyName in myObject) { document.writeln( propertyName + " : " + myObject[propertyName] ); }但令我惊讶的是,输出是
name : Cody status : Surprised forEach : function (obj, callback) { for (prop in obj) { if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") { callback(prop); } } }为什么?页面上的另一个脚本扩展了Object原型:
Object.prototype.forEach = function (obj, callback) { for ( prop in obj ) { if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) { callback( prop ); } } };
6> Andrew Hedge..:for (prop in obj) { alert(prop + ' = ' + obj[prop]); }
7> EmRa228..:简单的JavaScript代码:
for(var propertyName in myObject) { // propertyName is what you want. // You can get the value like this: myObject[propertyName] }jQuery的:
jQuery.each(obj, function(key, value) { // key is what you want. // The value is in: value });
8> davenpcj..:我发现它...
for (property in object) { // do stuff }
将列出所有属性,因此列出窗口对象上的所有全局声明的变量.
9> Chtiwi Malek..:以下是枚举对象属性的方法:
var params = { name: 'myname', age: 'myage' } for (var key in params) { alert(key + "=" + params[key]); }
10> dkl..:如果您使用的是Underscore.js库,则可以使用功能键:
_.keys({one : 1, two : 2, three : 3}); => ["one", "two", "three"]
11> Walle Cyril..:您可以使用
for
of循环。如果要使用数组:
Object.keys(object1)
参考 Object.keys()
12> Fabio Montef..:Python的dict有'keys'方法,这非常有用.我认为在JavaScript中我们可以有这样的东西:
function keys(){ var k = []; for(var p in this) { if(this.hasOwnProperty(p)) k.push(p); } return k; } Object.defineProperty(Object.prototype, "keys", { value : keys, enumerable:false });编辑:但@ carlos-ruana的答案非常有效.我测试了Object.keys(窗口),结果就是我的预期.
5年后编辑:扩展并不是一个好主意
Object
,因为它可能与其他可能想要keys
在其对象上使用的库发生冲突,并且会导致项目出现不可预测的行为.@ carlos-ruana回答是获取对象键的正确方法.