我如何枚举一个JavaScript对象的属性?

我实际上想列出所有已定义的变量及其值,但我已经了解到,定义变量实际上创建了窗口对象的属性。


当前回答

我认为一个让我吃惊的案例是相关的:

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 );
    }
  }
};

其他回答

如果你使用的是Underscore.js库,你可以使用函数键:

_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
for (prop in obj) {
    alert(prop + ' = ' + obj[prop]);
}

如果您试图枚举属性以便针对对象编写新代码,我建议使用像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..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()没有任何缺点。

我认为一个让我吃惊的案例是相关的:

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 );
    }
  }
};