题 如何使用对象作为成员遍历纯JavaScript对象?


如何遍历JavaScript对象中的所有成员,包括作为对象的值。

例如,我怎么能循环这个(访问每个的“your_name”和“your_message”)?

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar"
    }
}

1247
2018-05-28 16:18


起源


可能重复 循环遍历JavaScript对象 - BuZZ-dEE


答案:


for (var key in validation_messages) {
    // skip loop if the property is from prototype
    if (!validation_messages.hasOwnProperty(key)) continue;

    var obj = validation_messages[key];
    for (var prop in obj) {
        // skip loop if the property is from prototype
        if(!obj.hasOwnProperty(prop)) continue;

        // your code
        alert(prop + " = " + obj[prop]);
    }
}

1802
2018-05-28 16:20



Internet Explorer不同意(叹),当你做obj [prop]时,“对象不支持这个属性或方法”。我还没有找到解决方案。 - user999717
如果你正在使用jQuery,$ .each()/ does /在IE中工作。 - user999717
@MildFuzz实际上如果你认为JS对象不需要数字键是有意义的。你不能只是遍历一个对象。 JS的 for in 与传统非常相似 foreach。 - Jake Wilson
for ... in是一个很好的解决方案,但是如果你在for()循环中使用promises要小心,因为如果你在循环中创建一个var,你就不能在promise' then-function中使用它。你在循环中的var只存在一次,所以它在每个then-function中都有相同的,甚至是最后一个值。如果您有这个问题,请尝试“Object.keys(obj).forEach”或我的答案如下。 - Biber


在ECMAScript 5下,您可以组合使用 Object.keys() 和 Array.prototype.forEach()

var obj = {
  first: "John",
  last: "Doe"
};

//
//	Visit non-inherited enumerable keys
//
Object.keys(obj).forEach(function(key) {

  console.log(key, obj[key]);

});


569
2018-04-20 22:04



+1代码的简洁,但显然,并没有令人惊讶的效率。 JSPerf - for in vs Object.keys - techiev2
使用此方法时要小心此错误:“TypeError:在非对象上调用Object.keys”。该 for ... in ... hasOwnProperty 对于任何东西都可以调用模式,据我所知(对象,数组,空,未定义,真,假,数字原语,对象)。 - theazureshadow
请注意,IE7不支持此功能。 - Paul D. Waite
@ techiev2那些测试从未有效。有关当前的性能状态,请参阅我更新的: jsperf.com/objdir/20 - OrganicPanda
@ techiev2:不是 Object.keys() 这使得它变慢,而不是 forEach() 并重复访问 .length!如果你使用经典 for - 反过来,它几乎快了两倍 for..in+ hasOwnProperty() 在Firefox 33中。 - CoDEmanX


这个问题

for (var key in validation_messages) {
   var obj = validation_messages[key];
   for (var prop in obj) {
      alert(prop + " = " + obj[prop]);
   }
}

是你还将遍历原始对象的原型。

有了这个,你会避免它:

for (var key in validation_messages) {
   if (validation_messages.hasOwnProperty(key)) {
      var obj = validation_messages[key];
      for (var prop in obj) {
         if (obj.hasOwnProperty(prop)) {
            alert(prop + " = " + obj[prop]);
         }
      }
   }
}

364
2018-05-19 20:58



简而言之:检查 hasOwnProperty 你的内心 for - in 循环。 - Rory O'Kane
请注意,仅当您的对象具有原型方法时才需要这样做。例如,如果您循环的对象只是一个JSON对象,则不需要此检查。 - rednaw
@rednaw为了安全起见,我使用该检查,因为可以修改Object.prototype。没有理智的脚本会这样做,但你无法控制疯狂的浏览器扩展可能在你的页面中运行哪些脚本。浏览器扩展在您的页面中运行(在大多数浏览器上)并且它们可能导致奇怪的问题(例如,将window.setTimeout设置为null!)。 - robocat


ES6 你可以像这样循环一个对象:(使用 箭头功能

Object.keys(myObj).forEach(key => {
    console.log(key);          // the name of the current key.
    console.log(myObj[key]);   // the value of the current key.
});

jsbin

ES7 您可以使用 Object.entries 代替 Object.keys 并循环遍历这样的对象:

Object.entries(myObj).forEach(([key, val]) => {
    console.log(key);          // the name of the current key.
    console.log(val);          // the value of the current key.
});

以上也可以作为一个 一个班轮

Object.keys(myObj).forEach(key => console.log(key, myObj[key]));

jsbin

如果您想要遍历嵌套对象,也可以使用 递归 功能(ES6):

const loopNestedObj = (obj) => {
  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === 'object') loopNestedObj(obj[key]);  // recurse.
    else console.log(key, obj[key]);  // or do something with key and val.
  });
};

jsbin

与上面的功能相同,但使用ES7 Object.entries 代替 Object.keys

const loopNestedObj = (obj) => {
  Object.entries(obj).forEach(([key, val]) => {
    if (val && typeof val === 'object') loopNestedObj(val);  // recurse.
    else console.log(key, val);  // or do something with key and val.
  });
};

如果你进入 函数式编程 您可以使用 Object.keys/Object.entries 枚举对象,然后处理值,然后使用 reduce() 转换回新对象。

const loopNestedObj = (obj) => 
  Object.keys(obj)
    // Use .filter(), .map(), etc. if you need.
    .reduce((newObj, key) => 
      (obj[key] && typeof obj[key] === 'object') ?
        {...newObj, [key]: loopNestedObj(obj[key])} :  // recurse.
        {...newObj, [key]: obj[key]},                  // Define value.
      {});

145
2018-01-09 14:22



对于使用Object.entries示例的ES7,需要在括号中包含箭头函数参数[key,val],如:`Object.entries(myObj).forEach(([key,val])=> {/ * statements * /} - Puiu
我认为添加一个事实是有用的,即Object.entries和Object.keys不会遍历原型,这是它与for in构造之间的巨大差异。 - steviejay


运用 Underscore.js的 _.each

_.each(validation_messages, function(value, key){
    _.each(value, function(value, key){
        console.log(value);
    });
});

93
2017-09-16 12:11



谢谢蒂姆,使用下划线非常好,有一个快速和干净的选择。 - The Coder


如果你使用递归,你可以返回任何深度的对象属性 -

function lookdeep(object){
    var collection= [], index= 0, next, item;
    for(item in object){
        if(object.hasOwnProperty(item)){
            next= object[item];
            if(typeof next== 'object' && next!= null){
                collection[index++]= item +
                ':{ '+ lookdeep(next).join(', ')+'}';
            }
            else collection[index++]= [item+':'+String(next)];
        }
    }
    return collection;
}

//example

var O={
    a:1, b:2, c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
};
var lookdeepSample= 'O={'+ lookdeep(O).join(',\n')+'}';


/*  returned value: (String)
O={
    a:1, 
    b:2, 
    c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
}

*/

52
2018-05-28 18:03



注意循环,比如在DOM节点上调用它。 - theazureshadow


我知道这已经很晚了,但我花了2分钟来编写AgileJon的优化和改进版本的答案:

var key, obj, prop, owns = Object.prototype.hasOwnProperty;

for (key in validation_messages ) {

    if (owns.call(validation_messages, key)) {

        obj = validation_messages[key];

        for (prop in obj ) {

            // using obj.hasOwnProperty might cause you headache if there is
            // obj.hasOwnProperty = function(){return false;}
            // but owns will always work 
            if (owns.call(obj, prop)) {
                console.log(prop, "=", obj[prop]);
            }

        }

    }

}

29
2017-09-05 06:17



你为什么要存放 hasOwnProperty 在 owns 然后打电话 owns.call(obj, prop) 而不只是打电话 obj.hasOwnProperty(prop) 如 这个答案 呢? - Rory O'Kane
因为 obj 可能有 hasOwnProperty 自定义的函数,所以不会使用它 Object.prototype。你可以尝试之前 for 这样循环 obj.hasOwnProperty = function(){return false;} 并且它不会迭代任何属性。 - Azder
@Azder +1答案和+1,如果我可以为Object.prototype.hasOwnProperty的好事。我之前在下划线库的源代码中看到过,但不知道为什么。 - Samuel