Как пройти через простой объект JavaScript с объектами в качестве членов? - PullRequest
1437 голосов
/ 28 мая 2009

Как я могу перебрать все элементы в объекте 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"
    }
}

Ответы [ 21 ]

1992 голосов
/ 28 мая 2009
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]);
    }
}
693 голосов
/ 21 апреля 2011

В 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]);

});
377 голосов
/ 20 мая 2010

проблема с этим

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]);
         }
      }
   }
}
221 голосов
/ 09 января 2017

В 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.
      {});
93 голосов
/ 16 сентября 2012

Использование Underscore.js's _.each:

_.each(validation_messages, function(value, key){
    _.each(value, function(value, key){
        console.log(value);
    });
});
54 голосов
/ 28 мая 2009

Если вы используете рекурсию, вы можете вернуть свойства объекта любой глубины -

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
}

*/
34 голосов
/ 24 сентября 2017

Этот ответ представляет собой совокупность решений, которые были предоставлены в этом пост с некоторой производительностью обратные связи . Я думаю, что есть 2 сценарии использования и ОП не указали, нужен ли ему доступ к ключам для их использования во время цикла.

I. ключи должны быть доступны,

approach подход of и Object.keys

let k;
for (k of Object.keys(obj)) {

    /*        k : key
     *   obj[k] : value
     */
}

approach подход in

let k;
for (k in obj) {

    /*        k : key
     *   obj[k] : value
     */
}

Используйте это с осторожностью, так как это может напечатать свойства прототипа obj

approach подход ES7

for (const [key, value] of Object.entries(obj)) {

}

Однако во время редактирования я бы не рекомендовал метод ES7, потому что JavaScript инициализирует множество переменных внутри для построения этой процедуры (см. Отзывы для подтверждения). Если вы не разрабатываете огромное приложение, которое заслуживает оптимизации, тогда это нормально, но если оптимизация является вашим приоритетом, вы должны подумать об этом.

II. нам просто нужно получить доступ к каждому значению,

approach of и Object.values подход

let v;
for (v of Object.values(obj)) {

}

Больше отзывов о тестах:

  • Кэширование Object.keys или Object.values производительность незначительна

Например,

const keys = Object.keys(obj);
let i;
for (i of keys) {
  //
}
// same as
for (i of Object.keys(obj)) {
  //
}
  • Для случая Object.values использование собственного цикла for с кэшированными переменными в Firefox кажется немного быстрее, чем использование цикла for...of. Однако разница не так важна, и Chrome работает for...of быстрее, чем собственный цикл for, поэтому я рекомендую использовать for...of при работе с Object.values в любом случае (4-й и 6-й тесты).

  • В Firefox цикл for...in очень медленный, поэтому, когда мы хотим кэшировать ключ во время итерации, лучше использовать Object.keys. Плюс Chrome работает обе структуры с одинаковой скоростью (1-й и последний тесты).

Вы можете проверить тесты здесь: https://jsperf.com/es7-and-misc-loops

29 голосов
/ 05 сентября 2012

Я знаю, что уже поздно, но мне понадобилось 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]);
            }

        }

    }

}
27 голосов
/ 28 мая 2009
for(var k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}
12 голосов
/ 03 июля 2018

р - значение

for (var key in p) {
  alert(key + ' => ' + p[key]);
}

ИЛИ

Object.keys(p).forEach(key => { console.log(key, p[key]) })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...