如何枚举JavaScript对象的属性?
我实际上想列出所有已定义变量及其值,但我了解到定义变量实际上会创建一个window对象的属性。
如何枚举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..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()
没有任何负面影响。
Object.prototype.baz = 'quux';
语句会如何改变 myObject
对象? - JHBonariusmyObject.baz
:) 属性访问将沿着原型链向上查找,直到找到匹配项或原型链结束,因此它会在 Object.prototype
上找到 baz
并返回它。另外,我意识到这个答案是从2008年的,但我建议现在使用 Object.hasOwn(myObject, name)
。 - Ian Kim在现代浏览器(ECMAScript 5)中获取所有可枚举属性的方法:
Object.keys(obj) (查看链接以获取适用于旧版浏览器向后兼容的代码段)
或者同时获取非可枚举属性:
Object.getOwnPropertyNames(obj)
附加信息: 什么是可枚举属性?
Object.getOwnPropertyNames(obj)
就是你想要的,因为它可以获取非可枚举属性。 - vossad01getOwnPropertyNames
似乎无法与 ErrorEvent
对象一起使用:它只列出了 isTrusted
。然而,for( var pn in errEv ) console.log( pn ); }
确实可以工作。这很令人沮丧和不一致。 - Dai标准的方法,已经被多次提出,即:
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)已经实现了它。
我认为一个让我感到惊讶并且很有代表性的案例会很有帮助:
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]);
}
这是如何列举对象属性的方法:
var params = { name: 'myname', age: 'myage' }
for (var key in params) {
alert(key + "=" + params[key]);
}
简单的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
});
for (property in object) { // do stuff }
会列出所有属性,因此也会列出窗口对象上的所有全局声明变量。
for(x in {})
枚举任何内容感到惊讶,因为它看起来只是一个简单的字典键迭代。这非常意外,并且绝对值得特别警告。 - Glenn Maynardfor in
循环时提供警告是有益的,这样你就可以过滤继承的属性(如果需要的话)。为了迎合那些没有基本 JS 理解的人,给我的for loop
填充盲目的hasOwnProperty
检查是不必要的。 - Ruan Mendesfor (thing in set) { ... }
,这很容易犯的错误。 - Peter Wone