lista - ¿Cómo recorrer un objeto JavaScript simple con los objetos como miembros?
recorrer array de objetos javascript (19)
Esta respuesta es un agregado de las soluciones que se proporcionaron en esta publicación con algunos comentarios de rendimiento . Creo que hay 2 casos de uso y el OP no mencionó si necesita acceder a las teclas para usarlas durante el proceso de bucle.
I. las teclas necesitan ser accedidas,
✔ el enfoque de of
y Object.keys
let k;
for (k of Object.keys(obj)) {
/* k : key
* obj[k] : value
*/
}
✔ el enfoque in
let k;
for (k in obj) {
/* k : key
* obj[k] : value
*/
}
Utilice este con cautela, ya que podría imprimir propiedades prototipo de obj
✔ el enfoque ES7
for (const [key, value] of Object.entries(obj)) {
}
Sin embargo, en el momento de la edición, no recomendaría el método ES7, ya que JavaScript inicializa internamente muchas variables para construir este procedimiento (consulte los comentarios para obtener una prueba). A menos que no esté desarrollando una aplicación enorme que merezca optimización, entonces está bien, pero si la optimización es su prioridad, debe pensar en ello.
II. solo necesitamos acceder a cada valor,
✔ el enfoque de of
y Object.values
let v;
for (v of Object.values(obj)) {
}
Más comentarios sobre las pruebas:
- El
Object.keys
almacenamiento en caché deObject.keys
oObject.values
es despreciable
Por ejemplo,
const keys = Object.keys(obj);
let i;
for (i of keys) {
//
}
// same as
for (i of Object.keys(obj)) {
//
}
Para el caso de
Object.values
, el uso de un buclefor
nativo con variables en caché en Firefox parece ser un poco más rápido que usar un buclefor...of
. Sin embargo, la diferencia no es tan importante y Chrome se está ejecutandofor...of
más rápido que el nativofor
bucle, por lo que recomendaría utilizarfor...of
cuando se trate deObject.values
deObject.values
en cualquier caso (pruebas 4 y 6).En Firefox, el bucle
for...in
es realmente lento, por lo que cuando queremos almacenar en caché la clave durante la iteración, es mejor usarObject.keys
. Plus Chrome está ejecutando ambas estructuras a la misma velocidad (1ra y última prueba).
Puede consultar las pruebas aquí: https://jsperf.com/es7-and-misc-loops
¿Cómo puedo recorrer todos los miembros de un objeto de JavaScript, incluidos los valores que son objetos?
Por ejemplo, ¿cómo podría hacer esto?
var validation_messages = {
"key_1": {
"your_name": "jimmy",
"your_msg": "hello world"
},
"key_2": {
"your_name": "billy",
"your_msg": "foo equals bar"
}
}
Aquí viene la versión mejorada y recursiva de la solución de 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);
Esta solución funciona para todo tipo de diferentes profundidades.
Bajo ECMAScript 5, puede combinar Object.keys()
y 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]);
});
Creo que vale la pena señalar que jQuery $.each()
esto muy bien con $.each()
.
Consulte: https://api.jquery.com/each/
Por ejemplo:
$(''.foo'').each(function() {
console.log($(this));
});
$(this)
es el único elemento dentro del objeto. Cambie $(''.foo'')
a una variable si no quiere usar el motor de selección de jQuery.
ECMAScript-2017, recién finalizado hace un mes, introduce Object.values (). Así que ahora puedes hacer esto:
let v;
for (v of Object.values(validation_messages))
console.log(v.your_name); // jimmy billy
El problema con esto
for (var key in validation_messages) {
var obj = validation_messages[key];
for (var prop in obj) {
alert(prop + " = " + obj[prop]);
}
}
Es que también recorrerás el prototipo del objeto primitivo.
Con éste lo evitarás:
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]);
}
}
}
}
En ES6 puedes recorrer un objeto como este: (usando la función de flecha )
Object.keys(myObj).forEach(key => {
console.log(key); // the name of the current key.
console.log(myObj[key]); // the value of the current key.
});
En ES7 puede usar Object.entries
lugar de Object.keys
y recorrer un objeto como este:
Object.entries(myObj).forEach(([key, val]) => {
console.log(key); // the name of the current key.
console.log(val); // the value of the current key.
});
Lo anterior también funcionaría como una sola línea :
Object.keys(myObj).forEach(key => console.log(key, myObj[key]));
En caso de que también quiera recorrer objetos anidados, puede usar una función recursiva (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.
});
};
Igual que la función anterior, pero con ES7 Object.entries
lugar de 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.
});
};
Si está en la programación funcional , puede usar Object.keys
/ Object.entries
para enumerar el objeto, luego procesar los valores y luego usar reduce()
para volver a convertir a un nuevo objeto.
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.
{});
En ES7 puedes hacer:
for (const [key, value] of Object.entries(obj)) {
//
}
En mi caso (sobre la base de lo anterior) es posible cualquier número de niveles.
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'');}
resultado:
["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"]
La solución que me funciona es la siguiente.
_private.convertParams=function(params){
var params= [];
Object.keys(values).forEach(function(key) {
params.push({"id":key,"option":"Igual","value":params[key].id})
});
return params;
}
No pude conseguir las publicaciones anteriores para hacer exactamente lo que buscaba.
Después de jugar con las otras respuestas aquí, hice esto. Es hacky, pero funciona!
Para este objeto:
var myObj = {
pageURL : "BLAH",
emailBox : {model:"emailAddress", selector:"#emailAddress"},
passwordBox: {model:"password" , selector:"#password"}
};
... este código:
// 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 esto en la consola:
myObj.pageURL = BLAH
myObj.emailBox.model = emailAddress
myObj.emailBox.selector = #emailAddress
myObj.passwordBox.model = password
myObj.passwordBox.selector = #password
Otra opción:
var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
console.log(x);
}
Sé que es tarde, pero me tomó 2 minutos escribir esta versión optimizada y mejorada de la respuesta de 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]);
}
}
}
}
Si usa la recursión, puede devolver las propiedades del objeto de cualquier profundidad.
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
}
*/
Usando el _.each
de _.each
:
_.each(validation_messages, function(value, key){
_.each(value, function(value, key){
console.log(value);
});
});
p es el valor
for (var key in p) {
alert(key + '' => '' + p[key]);
}
O
Object.keys(p).forEach(key => { console.log(key, p[key]) })
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]);
}
}
for(var k in validation_messages) {
var o = validation_messages[k];
do_something_with(o.your_name);
do_something_else_with(o.your_msg);
}
for(var key in validation_messages){
for(var subkey in validation_messages[key]){
//code here
//subkey being value, key being ''yourname'' / ''yourmsg''
}
}