如果我不知道JavaScript对象的名称,如何访问其属性?

128

假设你有一个像这样的javascript对象:

var data = { foo: 'bar', baz: 'quux' };
您可以通过属性名称访问属性:
var foo = data.foo;
var baz = data["baz"];

如果您不知道属性的名称,是否有可能获取这些值?这些属性的无序性是否使得无法将它们区分开来?

在我的情况下,我特别考虑需要接受一系列名称-值对的函数,但属性的名称可能会更改。

到目前为止,我想到的方法是将属性的名称与数据一起传递给函数,但这感觉像是一个hack。如果可能的话,我更喜欢使用内省来完成这个任务。

8个回答

146
您可以按以下方式循环遍历键:
for (var key in data) {
  console.log(key);
}

这会记录“名称”和“值”。

如果您有更复杂的对象类型(不仅仅是像原始问题中的普通哈希对象),则需要仅循环遍历属于对象本身的键,而不是对象 prototype 上的键:

for (var key in data) {
  if (data.hasOwnProperty(key)) {
    console.log(key);
  }
}

正如您所指出的,键不保证以任何特定顺序出现。请注意这与以下内容的区别:

for each (var value in data) {
  console.log(value);
}

这个例子遍历值,所以会记录属性名称0。注意:for each语法大多数只在Firefox中支持,而其他浏览器不支持。
如果目标浏览器支持ES5,或者您的网站包含es5-shim.js(推荐),您也可以使用Object.keys
var data = { Name: 'Property Name', Value: '0' };
console.log(Object.keys(data)); // => ["Name", "Value"]

使用Array.prototype.forEach进行循环:

Object.keys(data).forEach(function (key) {
  console.log(data[key]);
});
// => Logs "Property Name", 0

你刚刚是编造了那个问题,然后还逃过了吗?干得好... =) - nickl-
这在Firefox中存在(文档),但是说得好,它并不普遍。我会更新答案来提到这一点。 - Ron DeVera
28
顺便提醒,使用警报(alert)来调试代码是不好的方式,建议使用console.log。 - StackOverflowed
这是在问题提出时最好的答案,但我将取消勾选它,因为后来的JS版本提供了更好的工具。 - Adam Lassek

68

旧版本的 JavaScript (< ES5) 需要使用 for..in 循环:

for (var key in data) {
  if (data.hasOwnProperty(key)) {
    // do something with key
  }
}

ES5引入了 Object.keysArray#forEach,这使得它更容易:

var data = { foo: 'bar', baz: 'quux' };

Object.keys(data); // ['foo', 'baz']
Object.keys(data).map(function(key){ return data[key] }) // ['bar', 'quux']
Object.keys(data).forEach(function (key) {
  // do something with data[key]
});

ES2017 引入了 Object.valuesObject.entries

Object.values(data) // ['bar', 'quux']
Object.entries(data) // [['foo', 'bar'], ['baz', 'quux']]

2
现在这实际上回答了问题,干得好@Adam Lassek,做得非常好。 - nickl-
在对象键中同时使用“name”和“value”是具有误导性的。该函数仅返回列表中的键,而不是值。对于初学者来说,“name1:'value1',name2:'value2'”将避免混淆。Object.keys(data); // ['name1','name2'] - nicholsonjf
3
我同意,经过修改以减少混淆。 - Adam Lassek

10
for(var property in data) {
    alert(property);
}

4

您经常需要查看对象实例的特定属性,而不包括其所有共享的原型方法和属性:

 Obj.prototype.toString= function(){
        var A= [];
        for(var p in this){
            if(this.hasOwnProperty(p)){
                A[A.length]= p+'='+this[p];
            }
        }

    return A.join(', ');
}

3
function getDetailedObject(inputObject) {
    var detailedObject = {}, properties;

    do {
        properties = Object.getOwnPropertyNames( inputObject );
        for (var o in properties) {
            detailedObject[properties[o]] = inputObject[properties[o]];
        }
    } while ( inputObject = Object.getPrototypeOf( inputObject ) );

    return detailedObject;
}

这将在一个新对象中获取所有属性及其值(继承或自有,可枚举或不可枚举)。原始对象保持不变。现在可以使用新对象进行遍历。

var obj = { 'b': '4' }; //example object
var detailedObject = getDetailedObject(obj);
for(var o in detailedObject) {
    console.log('key: ' + o + '   value: ' + detailedObject[o]);
}

1
你可以使用 Object.keys(),"它返回一个给定对象的可枚举属性名数组,顺序与普通循环相同。"
你可以使用任何对象来代替stats:

var stats = {
  a: 3,
  b: 6,
  d: 7,
  erijgolekngo: 35
}
/*  this is the answer here  */
for (var key in Object.keys(stats)) {
  var t = Object.keys(stats)[key];
  console.log(t + " value =: " + stats[t]);
}


你能添加更多的解释吗? - Keith Pinson
Object.keys(stats)[key] 没有意义,总是会返回 undefined - Adam Lassek

1
var obj = {
 a: [1, 3, 4],
 b: 2,
 c: ['hi', 'there']
 }
for(let r in obj){  //for in loop iterates all properties in an object
 console.log(r) ;  //print all properties in sequence
 console.log(obj[r]);//print all properties values
}

这个答案提供了OP所需的内容,但稍微描述一下你正在做什么以及为什么OP应该使用它会更好,此外,在使用for in迭代对象时不要忘记.hasOwnProperty() - Muhammad Omer Aslam
谢谢,我同意.hasOwnProperty()迭代对象,但它是为了检查条件而迭代的,然而使用它我们不能打印对象的所有属性。如果我错了,请纠正我。 - Mayank_VK
hasOwnProperty() 方法返回一个布尔值,指示对象是否具有指定属性作为其自身属性(而不是继承它)。请参见此示例 - Muhammad Omer Aslam

-2
var attr, object_information='';

for(attr in object){

      //Get names and values of propertys with style (name : value)
      object_information += attr + ' : ' + object[attr] + '\n'; 

   }


alert(object_information); //Show all Object

这并没有为被接受的答案增加任何内容,并且以最不实用的方式呈现信息。而且它也没有考虑到继承属性。 - Adam Lassek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接