如何枚举JavaScript对象的属性?
如何枚举JavaScript对象的属性?
我实际上想列出所有已定义的变量及其值,但是我了解到定义一个变量实际上会创建window对象的属性。
解决方案
回答
很简单:
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(对象中的属性{//做东西})将列出所有属性,因此将列出窗口对象上的所有全局声明的变量。
回答
使用" 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()"没有任何弊端。
回答
如果我们试图枚举属性以针对该对象编写新代码,则建议使用Firebug之类的调试器以可视方式查看它们。
另一个方便的技术是使用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"]}'
http://www.prototypejs.org/api/object/tojson
回答
for (prop in obj) { alert(prop + ' = ' + obj[prop]); }
回答
我认为举个例子令我吃惊:
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 (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)已经实现了它。