Как пропустить простой объект 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"
    }
}

Ответы

Ответ 1

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

Ответ 2

В соответствии с 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]);

});

Ответ 3

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

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

Ответ 4

В ES6/2015 вы можете перемещаться по объекту следующим образом: (используя функцию стрелки)

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/2016 вы можете использовать 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.entries(myObj).forEach(([key, val]) => console.log(key, val));

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.entries() в сочетании с Object.fromEntries() (ES10/2019):

const loopNestedObj = obj =>
  Object.fromEntries(
    Object.entries(obj).map(([key, val]) => {
      if (val && typeof val === "object") [key, loopNestedObj(val)]; // recurse
      else [key, updateMyVal(val)]; // or do something with key and val.
    })
  );

Ответ 5

Используя Underscore.jss _.each:

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

Ответ 6

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

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
}

*/

Ответ 7

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

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

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

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

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

in подходе

let k;
for (k in obj) {

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

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

✔ подход ES7

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

}

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

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

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 быстрее, чем native for цикла, поэтому я бы рекомендовал использовать for...of при работе с Object.values в любом случае (4-й и 6-й тесты).

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

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

Ответ 8

Я знаю это waaay поздно, но мне потребовалось 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]);
            }

        }

    }

}

Ответ 9

for(var k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}

Ответ 10

p - значение

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

ИЛИ

Object.keys(p).forEach(key => { console.log(key, p[key]) })

Ответ 11

В ES7 вы можете:

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

Ответ 12

for(var key in validation_messages){
    for(var subkey in validation_messages[key]){
        //code here
        //subkey being value, key being 'yourname' / 'yourmsg'
    }
}

Ответ 13

Здесь идет улучшенная и рекурсивная версия решения AgileJon (demo):

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

    if(typeof obj[key] !== 'object'){
      //your code
      console.log(key+" = "+obj[key]);
    } else {
      loopThrough(obj[key]);
    }
  }
}
loopThrough(validation_messages);

Это решение работает для всех видов разной глубины.

Ответ 14

Несколько способов сделать это...

1) 2 слоя для... в петле...

for (let key in validation_messages) {
   const vmKeys = validation_messages[key];
   for (let vmKey in vmKeys) {
      console.log(vmKey + vmKeys[vmKey]);
   }
}

2) Использование Object.key

Object.keys(validation_messages).forEach(key => {
   const vmKeys = validation_messages[key];
   Object.keys(vmKeys).forEach(key => {
    console.log(vmKeys + vmKeys[key]);
   });
});

3) Рекурсивная функция

const recursiveObj = obj => {
  for(let key in obj){
    if(!obj.hasOwnProperty(key)) continue;

    if(typeof obj[key] !== 'object'){
      console.log(key + obj[key]);
    } else {
      recursiveObj(obj[key]);
    }
  }
}

И назовите это как:

recursiveObj(validation_messages);

Ответ 15

Другая опция:

var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
    console.log(x);
}

Ответ 16

ECMAScript-2017, только что завершившийся месяц назад, представляет Object.values ​​(). Теперь вы можете сделать это:

let v;
for (v of Object.values(validation_messages))
   console.log(v.your_name);   // jimmy billy

Ответ 17

Мне кажется, стоит отметить, что jQuery отлично сортирует это с помощью $.each().

Смотрите: https://api.jquery.com/each/

Например:

$('.foo').each(function() {
    console.log($(this));
});

$(this) является единственным элементом внутри объекта. Примените $('.foo') к переменной, если вы не хотите использовать механизм селектора jQuery.

Ответ 18

var obj={
name:"SanD",
age:"27"
}
Object.keys(obj).forEach((key)=>console.log(key,obj[key]));

Ответ 19

Я не мог получить вышеуказанные сообщения, чтобы делать то, что было после.

После игры с другими ответами я сделал это. Он взломан, но он работает!

Для этого объекта:

var myObj = {
    pageURL    : "BLAH",
    emailBox   : {model:"emailAddress", selector:"#emailAddress"},
    passwordBox: {model:"password"    , selector:"#password"}
};

... этот код:

// Get every value in the object into a separate array item ...
function buildArray(p_MainObj, p_Name) {
    var variableList = [];
    var thisVar = "";
    var thisYes = false;
    for (var key in p_MainObj) {
       thisVar = p_Name + "." + key;
       thisYes = false;
       if (p_MainObj.hasOwnProperty(key)) {
          var obj = p_MainObj[key];
          for (var prop in obj) {
            var myregex = /^[0-9]*$/;
            if (myregex.exec(prop) != prop) {
                thisYes = true;
                variableList.push({item:thisVar + "." + prop,value:obj[prop]});
            }
          }
          if ( ! thisYes )
            variableList.push({item:thisVar,value:obj});
       }
    }
    return variableList;
}

// Get the object items into a simple array ...
var objectItems = buildArray(myObj, "myObj");

// Now use them / test them etc... as you need to!
for (var x=0; x < objectItems.length; ++x) {
    console.log(objectItems[x].item + " = " + objectItems[x].value);
}

... производит это в консоли:

myObj.pageURL = BLAH
myObj.emailBox.model = emailAddress
myObj.emailBox.selector = #emailAddress
myObj.passwordBox.model = password
myObj.passwordBox.selector = #password

Ответ 20

Объект становится итератором, когда он реализует метод .next()

fooobar.com/questions/583/...

Ответ 21

Решение, которое работает для меня, заключается в следующем

_private.convertParams=function(params){
    var params= [];
    Object.keys(values).forEach(function(key) {
        params.push({"id":key,"option":"Igual","value":params[key].id})
    });
    return params;
}

Ответ 22

В моем случае (на основе предыдущего) возможно любое количество уровней.

var myObj = {
    rrr: undefined,
    pageURL    : "BLAH",
    emailBox   : {model:"emailAddress", selector:"#emailAddress"},
    passwordBox: {model:"password"    , selector:"#password"},
    proba: {odin:{dva:"rr",trr:"tyuuu"}, od:{ff:5,ppa:{ooo:{lll:'lll'}},tyt:'12345'}}
};


function lookdeep(obj,p_Name,gg){
    var A=[], tem, wrem=[], dd=gg?wrem:A;
    for(var p in obj){
        var y1=gg?'':p_Name, y1=y1 + '.' + p;
        if(obj.hasOwnProperty(p)){
           var tem=obj[p];
           if(tem && typeof tem=='object'){
               a1=arguments.callee(tem,p_Name,true);
               if(a1 && typeof a1=='object'){for(i in a1){dd.push(y1 + a1[i])};}
            }
            else{
               dd.push(y1 + ':' + String(tem));
            }
        }
    };
    return dd
};


var s=lookdeep(myObj,'myObj',false);
for (var x=0; x < s.length; ++x) {
console.log(s[x]+'\n');}

результат:

["myObj.rrr:undefined",
"myObj.pageURL:BLAH",
"myObj.emailBox.model:emailAddress",
"myObj.emailBox.selector:#emailAddress",
"myObj.passwordBox.model:password",
"myObj.passwordBox.selector:#password",
"myObj.proba.odin.dva:rr",
"myObj.proba.odin.trr:tyuuu",
"myObj.proba.od.ff:5",
"myObj.proba.od.ppa.ooo.lll:lll",
"myObj.proba.od.tyt:12345"]