How do I enumerate the properties of a JavaScript object?
如何枚举javascript对象的属性?
我实际上想列出所有定义的变量及其值,但我已经了解到定义一个变量实际上会创建一个窗口对象的属性。
足够简单:
1 2 3 4 | for(var propertyName in myObject) { // propertyName is what you want // you can get the value like this: myObject[propertyName] } |
现在,您将无法通过这种方式获得私有变量,因为它们不可用。
编辑:@bitwiseplatypus是正确的,除非您使用
这就是说,
编辑2:@bitwiseplatypus提出了这样一种情况,即如果有人在某个时间点(比您最初(通过原型)向您的对象添加属性/方法时晚)将发生这种情况,虽然这确实可能导致意外行为,但我个人并不认为这完全是我的问题。只是意见问题。此外,如果我在构建对象的过程中使用原型设计事物,并且有代码迭代对象的属性,并且我想要所有继承的属性,那该怎么办?我不会用
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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' |
要避免在枚举中包含继承的属性,请检查
1 2 3 4 5 | for (var name in myObject) { if (myObject.hasOwnProperty(name)) { alert(name); } } |
编辑:我不同意JasonBunting的说法,即我们不需要担心枚举继承的属性。枚举继承的属性是有危险的,因为它可以改变代码的行为。
不管这个问题是否存在于其他语言中,事实是它存在,而且javascript特别容易受到攻击,因为对对象原型的修改会影响子对象,即使修改是在实例化之后进行的。
这就是为什么javascript提供
已经多次提出的标准方法是:
1 2 3 | for (var name in myObject) { alert(name); } |
然而,InternetExplorer6、7和8在JavaScript解释器中有一个bug,它的作用是不枚举某些键。如果运行此代码:
1 2 3 4 | var obj = { toString: 12}; for (var name in obj) { alert(name); } |
如果会在除IE.IE之外的所有浏览器中警告"12",则会忽略此键。受影响的关键值包括:
isPrototypeOf hasOwnProperty toLocaleString toString valueOf
为了安全起见,你必须使用如下工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | for (var key in myObject) { alert(key); } var shadowedKeys = [ "isPrototypeOf", "hasOwnProperty", "toLocaleString", "toString", "valueOf" ]; for (var i=0, a=shadowedKeys, l=a.length; i<l; i++) { if map.hasOwnProperty(a[i])) { alert(a[i]); } } |
好消息是,ecmascript5定义了
在现代浏览器(EcmaScript 5)中,要获取所有可枚举属性,可以执行以下操作:
对象键(obj)(检查链接以获取旧浏览器上向后兼容性的代码段)
或者获取不可枚举的属性:
对象.getownprotynames(obj)
检查ECMAScript 5兼容性表
其他信息:什么是可枚举属性?
我认为一个让我吃惊的例子是相关的:
1 2 3 4 | var myObject = { name:"Cody", status:"Surprised" }; for (var propertyName in myObject) { document.writeln( propertyName +" :" + myObject[propertyName] ); } |
但令我惊讶的是,输出
1 2 3 4 5 6 7 8 9 | name : Cody status : Surprised forEach : function (obj, callback) { for (prop in obj) { if (obj.hasOwnProperty(prop) && typeof obj[prop] !=="function") { callback(prop); } } } |
为什么?页面上的另一个脚本扩展了对象原型:
1 2 3 4 5 6 7 | Object.prototype.forEach = function (obj, callback) { for ( prop in obj ) { if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !=="function" ) { callback( prop ); } } }; |
1 2 3 | for (prop in obj) { alert(prop + ' = ' + obj[prop]); } |
简单的javascript代码:
1 2 3 4 | for(var propertyName in myObject) { // propertyName is what you want. // You can get the value like this: myObject[propertyName] } |
jQuery:
1 2 3 4 | jQuery.each(obj, function(key, value) { // key is what you want. // The value is in: value }); |
我找到了它…
以下是枚举对象属性的方法:
1 2 3 4 5 | var params = { name: 'myname', age: 'myage' } for (var key in params) { alert(key +"=" + params[key]); } |
如果使用的是underline.js库,则可以使用功能键:
1 2 | _.keys({one : 1, two : 2, three : 3}); => ["one","two","three"] |
python的dict有"keys"方法,这非常有用。我认为在javascript中我们可以有这样的功能:
1 2 3 4 5 6 7 8 9 | 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(window),结果是我所期望的。
5年后编辑:扩展
您可以使用循环的
如果要使用数组,请使用:
引用object.keys()。
如果您试图枚举属性以便针对对象编写新代码,我建议使用类似Firebug的调试器来直观地查看它们。
另一种方便的技术是使用原型的object.tojson()将对象序列化为json,它将同时显示属性名和值。
1 2 3 | var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']}; Object.toJSON(data); //-> '{"name":"Violet","occupation":"character","age": 25,"pets": ["frog","rabbit"]}' |
http://www.prototypejs.org/api/object/tojson
我仍然是javascript的初学者,但我编写了一个小函数来递归地打印对象及其子对象的所有属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | getDescription(object, tabs) { var str ="{ "; for (var x in object) { str += Array(tabs + 2).join("\t") + x +":"; if (typeof object[x] === 'object' && object[x]) { str += this.getDescription(object[x], tabs + 1); } else { str += object[x]; } str +=" "; } str += Array(tabs + 1).join("\t") +"}"; return str; } |