Как пройти через простой объект 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"
}
}
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. });на 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]));в случае, если вы хотите, чтобы петли через вложенные объекты, а также, вы можете использовать рекурсивные функция (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. }); };то же, что и функция выше, но с 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.valuescase, используя родной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]) })
вот улучшенная и рекурсивная версия решения 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