Come eseguire il ciclo di un object JavaScript semplice con gli oggetti come membri?

Come posso scorrere tutti i membri in un object JavaScript compresi i valori che sono oggetti.

Ad esempio, come potrei fare un loop su questo (accedendo a “your_name” e “your_message” per ciascuno)?

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

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

Sotto ECMAScript 5, puoi combinare Object.keys() e 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]); }); 

Il problema con questo

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

è che si scorrerà anche attraverso il prototipo dell’object primitivo.

Con questo lo eviterai:

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

In ES6 puoi eseguire il loop di un object come questo: (usando la funzione freccia )

 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

In ES7 è ansible utilizzare Object.entries anziché Object.keys e scorrere un object come questo:

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

Quanto sopra funzionerebbe anche come one-liner :

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

jsbin

Nel caso in cui si desideri eseguire il ciclo anche attraverso oggetti nidificati, è ansible utilizzare una funzione ricorsiva (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

Come sopra, ma con Object.entries Object.entries invece di 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. }); }; 

Se si utilizza la programmazione funzionale, è ansible utilizzare Object.keys / Object.entries per enumerare l’object, quindi elaborare i valori e quindi utilizzare reduce() per riconvertire in un nuovo object.

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

Usando il file _.each di Underscore.js :

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

Se usi la ricorsione puoi restituire le proprietà dell’object di qualsiasi profondità

 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 } */ 

So che è mooolto tardi, ma mi ci sono voluti 2 minuti per scrivere questa versione ottimizzata e migliorata della risposta di 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); } 

Questa risposta è un aggregato delle soluzioni che sono state fornite in questo post con alcuni feedback sulle prestazioni . Penso che ci siano 2 casi d’uso e l’OP non ha menzionato se ha bisogno di accedere alle chiavi per usarle durante il processo di loop.

I. le chiavi devono essere accessibili,

✔ l’approccio of e Object.keys

 let k; for (k of Object.keys(obj)) { /* k : key * obj[k] : value */ } 

✔ l’approccio in

 let k; for (k in obj) { /* k : key * obj[k] : value */ } 

Utilizzare questo con caucanvas, in quanto potrebbe stampare le proprietà del prototipo di oggetti

✔ l’approccio ES7

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

Tuttavia, al momento della modifica non raccomanderei il metodo ES7, perché JavaScript inizializza un sacco di variabili internamente per build questa procedura (vedere i feedback per la prova). A meno che tu non stia sviluppando un’app enorme che merita l’ottimizzazione, allora va bene, ma se l’ottimizzazione è la tua priorità, dovresti pensarci.

II. dobbiamo solo accedere a ciascun valore,

✔ l’approccio of e Object.values

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

Ulteriori commenti sui test:

  • Object.keys prestazioni di Caching Object.keys o Object.values sono trascurabili

Per esempio,

 const keys = Object.keys(obj); let i; for (i of keys) { // } // same as for (i of Object.keys(obj)) { // } 
  • Per il caso Object.values , l’utilizzo di un loop nativo for ciclo con variabili memorizzate nella cache in Firefox sembra essere un po ‘più veloce rispetto all’utilizzo di un ciclo for...of . Tuttavia la differenza non è così importante e Chrome è in esecuzione for...of più veloce del ciclo nativo for loop, quindi consiglierei di usare for...of quando si tratta di Object.values in qualsiasi caso (4 ° e 6 ° test).

  • In Firefox, il ciclo for...in è molto lento, quindi quando vogliamo memorizzare la chiave durante l’iterazione è meglio usare Object.keys . Inoltre Chrome esegue entrambe le strutture a parità di velocità (primo e ultimo test).

Puoi controllare i test qui: 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' } } 

In ES7 puoi fare:

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

Ecco la versione migliorata e ricorsiva della soluzione di 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); 

Questa soluzione funziona per tutti i tipi di profondità diverse.

Un’altra opzione:

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

p è il valore

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

O

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

Penso che valga la pena sottolineare che jQuery lo classifica bene con $.each() .

Vedi: https://api.jquery.com/each/

Per esempio:

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

$(this) è il singolo object all’interno dell’object. Scambia $('.foo') in una variabile se non vuoi usare il motore di selezione di jQuery.

ECMAScript-2017, appena finalizzato un mese fa, introduce Object.values ​​(). Quindi ora puoi fare questo:

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

Non riuscivo a ottenere i post di cui sopra per quello che cercavo.

Dopo aver giocato con le altre risposte qui, ho fatto questo. È hacky, ma funziona!

Per questo object:

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

… questo codice:

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

... produce questo nella console:

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

La soluzione che funziona per me è la seguente

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

Nel mio caso (sulla base del precedente) è ansible qualsiasi numero di livelli.

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

risultato:

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