Как пройти через простой объект 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"
}
}
289   19  

19 ответов:

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

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

});

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

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

на 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.
      {});

используя подчеркивания.в JS это _.each:

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

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

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
}

*/

Я знаю, что это 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]);
            }

        }

    }

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

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

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

✔ the of и Object.keys подход

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

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

✔ the 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. нам просто нужно получить доступ к каждому значению,

✔ the 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 case, используя родной 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

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

p-это значение

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

или

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

в ES7 вы можете сделать:

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

вот улучшенная и рекурсивная версия решения AgileJon (демо):

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

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

другой вариант:

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

Я думаю, стоит отметить, что jQuery хорошо разбирается с $.each().

см.:https://api.jquery.com/each/

например:

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

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

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

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

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

после игры с другими ответами здесь, я сделал это. Это hacky, но это работает!

для этого элемента:

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

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

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

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

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"]

Comments

    Ничего не найдено.