我如何枚举JavaScript对象的属性?
我如何枚举JavaScript对象的属性?
我实际上想要列出所有已定义的variables及其值,但是我已经了解到,定义variables实际上会创build窗口对象的一个属性。
够简单:
for(var propertyName in myObject) { // propertyName is what you want // you can get the value like this: myObject[propertyName] }
现在,你不会以这种方式获得私有variables,因为它们不可用。
编辑: @bitwiseplatypus是正确的,除非你使用hasOwnProperty()
方法,你会得到inheritance的属性 – 但是,我不知道为什么有人熟悉面向对象的编程会期望更less! 通常情况下,有人提出这个问题已经受到了道格拉斯·克罗克福德(Douglas Crockford)关于这个问题的警告,这仍然让我感到困惑。 同样,inheritance是面向对象语言的正常部分,因此是JavaScript的一部分,尽pipe它是典型的。
现在说, hasOwnProperty()
对于过滤很有用,但是我们不需要发出警告,就像在获取inheritance属性时有一些危险一样。
编辑2: @bitwiseplatypus带来的情况将发生应该有人添加属性/方法的时间点比你最初写对象(通过它的原型)的时间点 – 而这是真的,这可能会导致意外的行为,我个人并不认为这完全是我的问题。 只是一个意见的问题。 此外,如果我devise的东西,我在我的对象的build设过程中使用原型,但有代码迭代的对象的属性,我想要所有的inheritance属性? 我不会使用hasOwnProperty()
。 那么,假设稍后有人添加新的属性。 如果事情在这一点上performance不好,那是我的错吗? 我不这么认为。 我想这就是为什么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'
要避免在枚举中包含inheritance的属性,请选中hasOwnProperty()
:
for (var name in myObject) { if (myObject.hasOwnProperty(name)) { alert(name); } }
编辑:我不同意JasonBunting的声明,我们不必担心枚举inheritance属性。 在枚举inheritance的属性上存在着不期望的危险,因为它可以改变代码的行为。
这个问题在其他语言中是否存在并不重要; 事实是存在的,而且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<l; i++) { if map.hasOwnProperty(a[i])) { alert(a[i]); } }
好消息是,EcmaScript 5定义了Object.keys(myObject)
函数,它返回一个对象的键作为数组,并且一些浏览器(例如Safari 4)已经实现了它。
在现代浏览器(ECMAScript 5)中,您可以执行所有可枚举的属性:
Object.keys(obj) (检查链接以得到一个片段,以在旧浏览器上向后兼容)
或者也可以获得不可枚举的属性:
Object.getOwnPropertyNames(OBJ)
检查ECMAScript 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 ); } } };
for (prop in obj) { alert(prop + ' = ' + obj[prop]); }
我发现它… for (property in object) { // do stuff }
将列出所有的属性,因此窗口对象上的所有全局声明variables。
简单的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 });
如果您正在使用Underscore.js库,则可以使用function键 :
_.keys({one : 1, two : 2, three : 3}); => ["one", "two", "three"]
以下是枚举对象的属性的方法:
var params = { name: 'myname', age: 'myage' } for (var key in params) { alert(key + "=" + params[key]); }
Python的字典有'钥匙'的方法,这是非常有用的。 我认为在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的答案工作得很好。 我testing了Object.keys(窗口),结果是我所期望的。
如果你想枚举的属性,以写对对象的新代码,我会build议使用像Firebug的debugging器来查看它们的视觉。
另一个方便的技术是使用Prototype的Object.toJSON()来将对象序列化为JSON,这会向您显示属性名称和值。
var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']}; Object.toJSON(data); //-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
你可以使用for循环。
如果你想要一个数组使用Object.keys(object1)
我仍然是JavaScript的初学者,但我写了一个小函数来recursion地打印一个对象及其子对象的所有属性:
getDescription(object, tabs) { var str = "{\n"; 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 += "\n"; } str += Array(tabs + 1).join("\t") + "}"; return str; }