¿Cómo recorrer un objeto JavaScript simple con los objetos como miembros?

¿Cómo puedo recorrer todos los miembros en un objeto JavaScript, incluidos los valores que son objetos?

Por ejemplo, ¿cómo podría recorrer esto (accediendo a "tu_nombre" y "tu_mensaje" para cada uno)?

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

preguntado el 28 de mayo de 09 a las 13:05

posible duplicado de Recorrer el objeto JavaScript -

25 Respuestas

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

Respondido 21 ago 19, 03:08

Internet Explorer no está de acuerdo (suspiro), dice "Object no admite esta propiedad o método" cuando haces obj [prop]. Todavía tengo que encontrar una solución a esto. - user999717

@MildFuzz en realidad tiene sentido si considera que los objetos JS no necesariamente tienen claves numéricas. No puedes simplemente iterar a través de un objeto. JS for in es muy similar a un tradicional foreach. - jake wilson

for ... in es una buena solución, pero si usa promesas en el bucle for () - tenga cuidado, porque si crea una var en el bucle, no puede usarla en la función de promesa 'then. Su var en el bucle existe solo una vez, por lo que tiene en todas las funciones de entonces lo mismo, incluso el último valor. Si tiene ese problema, intente "Object.keys (obj) .forEach" o mi respuesta a continuación. - Castor

hasOwnProperty casi siempre es redundante para los navegadores modernos (IE9 +). - Filius

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

});

Respondido el 27 de diciembre de 17 a las 07:12

+1 para la brevedad del código, pero aparentemente no funciona tan eficientemente como para sorprendentemente. JSPerf - para in vs Object.keys - techiev2

Tenga cuidado con este error usando este enfoque: "TypeError: Object.keys llamado en non-object". La for ... in ... hasOwnProperty el patrón se puede llamar en cualquier cosa, por lo que puedo decir (objeto, matriz, nulo, indefinido, verdadero, falso, primitivo numérico, objetos). - la sombra azul

Tenga en cuenta que IE7 no es compatible con esto. - Pablo D. Waite

@ techiev2 esas pruebas nunca fueron válidas. Vea mis actualizados para el estado actual de rendimiento: jsperf.com/objdir/20 - Orgánica Panda

@ techiev2: no lo es Object.keys() lo que lo hace lento, es más bien el forEach() y el acceso repetido a .length! Si usa un clásico for-loop en su lugar, es casi el doble de rápido que for..in + hasOwnProperty() en Firefox 33. - CódigoManX

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

respondido 21 nov., 12:05

En resumen: comprobar hasOwnProperty dentro de su for-in bucles. - Rory O'Kane

Tenga en cuenta que esto solo es necesario si su objeto TIENE métodos de prototipo. Por ejemplo, si el objeto por el que está navegando es solo un objeto JSON, no necesitará esta comprobación. - gitaarik

@rednaw Para estar seguro, utilizo ese cheque porque Object.prototype se puede modificar. Ningún script en su sano juicio haría eso, pero no puede controlar qué scripts se pueden ejecutar en su página mediante extensiones de navegador insanas. Las extensiones del navegador se ejecutan en su página (en la mayoría de los navegadores) y pueden causar problemas extraños (por ejemplo, ¡establezca window.setTimeout en null!). - robogato

In ES6 / 2015 puede recorrer un objeto como este: (usando 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.
});

jsbin

In ES7 / 2016 puedes usar Object.entries en 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 un trazador de líneas:

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

jsbin

En caso de que desee recorrer también objetos anidados, puede utilizar un recursiva función (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

Igual que la función anterior, pero con ES7 Object.entries() en 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.
  });
};

Aquí recorremos los objetos anidados, cambiamos los valores y devolvemos un nuevo objeto de una sola vez usando Object.entries() combinado con 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.
    })
  );

Otra forma de recorrer objetos es usando para ... en y para ... de. Vea La respuesta bien escrita de @vdegenne.

Respondido el 31 de diciembre de 20 a las 12:12

para su ES7 usando el ejemplo de Object.entries, debe envolver los parámetros de la función de flecha [key, val] entre paréntesis como: `Object.entries (myObj) .forEach (([key, val]) => {/ * declaraciones * /} - puiu

Creo que sería útil agregar el hecho de que Object.entries y Object.keys no iteran sobre el prototipo, que es la gran diferencia entre este y el for in construct. - Steviesh

Usar Underscore.js's _.each:

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

Respondido el 17 de Septiembre de 16 a las 12:09

Gracias Tim, el uso de subrayado es definitivamente bueno para tener una opción rápida y limpia. - El codificador

Si usa la recursividad, puede devolver propiedades de 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
}

*/

Respondido 18 Jul 13, 01:07

Tenga cuidado con los bucles, como llamar a esto en un nodo DOM. - la sombra azul

Esta respuesta es un agregado de las soluciones que se proporcionaron en esta publicación con algunas retroalimentación de rendimiento. Creo que hay 2 casos de uso y el OP no mencionó si necesita acceder a las claves para usarlas durante el proceso de bucle.

I. es necesario acceder a las claves,

✔ el of y Object.keys enfoque

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

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

✔ el in enfoque

let k;
for (k in obj) {

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

Utilice este con precaución, ya que podría imprimir propiedades de 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, porque JavaScript inicializa una gran cantidad de variables internamente para construir este procedimiento (vea los comentarios como 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, debería pensar en ello.

II. solo necesitamos acceder a cada uno de los valores,

✔ el of y Object.values enfoque

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

}

Más comentarios sobre las pruebas:

  • Almacenamiento en caché Object.keys or Object.values el rendimiento es insignificante

Por ejemplo,

const keys = Object.keys(obj);
let i;
for (i of keys) {
  //
}
// same as
for (i of Object.keys(obj)) {
  //
}
  • Para Object.values caso, usando un nativo for bucle con variables en caché en Firefox parece ser un poco más rápido que usar un for...of círculo. Sin embargo, la diferencia no es tan importante y Chrome se está ejecutando for...of más rápido que el nativo for loop, por lo que recomendaría usar for...of cuando se trata de Object.values en cualquier caso (4ª y 6ª pruebas).

  • En Firefox, el for...in El bucle es realmente lento, por lo que cuando queremos almacenar en caché la clave durante la iteración, es mejor usar Object.keys. Además, Chrome ejecuta ambas estructuras a la misma velocidad (primera y última prueba).

Puedes consultar las pruebas aquí: https://jsperf.com/es7-and-misc-loops

Respondido 05 Abr '18, 03:04

¡El ejemplo de ES7 funciona a la perfección con React Native! - ty bailey

Bien explicado. Gracias - Alok Ranyan

Sé que es muy 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]);
            }

        }

    }

}

respondido 21 nov., 12:05

¿Por qué estás almacenando? hasOwnProperty in owns y luego llamando owns.call(obj, prop) en lugar de solo llamar obj.hasOwnProperty(prop) as esta respuesta ¿lo hace? - Rory O'Kane

Porque obj podría tener el hasOwnProperty función definida en sí misma, por lo que no utilizará la de Object.prototype. Puedes probar antes del for bucle como este obj.hasOwnProperty = function(){return false;} y no iterará sobre ninguna propiedad. - Azder

@Azder +1 por la respuesta y +1 si pudiera por lo bueno de Object.prototype.hasOwnProperty. Lo vi anteriormente dentro del código fuente de la biblioteca de subrayado, pero no sé por qué. - Samuel

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

contestado el 28 de mayo de 09 a las 17:05

p es el valor

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

OR

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

Respondido 03 Jul 18, 12:07

En ES7 puedes hacer:

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

Respondido 07 ago 17, 14:08

Hice algunas pruebas, este método es realmente lento cuando se trata de gran cantidad de datos. - vdegenne

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

contestado el 28 de mayo de 09 a las 17:05

Pocas formas de hacer eso ...

1) 2 capas para ... en bucle ...

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

2) Usar Object.key

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

3) Función recursiva

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

Y llámalo como:

recursiveObj(validation_messages);

Respondido el 21 de enero de 19 a las 12:01

Otra opción:

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

Respondido el 23 de diciembre de 16 a las 14:12

Probé su solución en Chrome 55.0 y aparece un error de tipo. Su respuesta se ve bien y concisa, si puede hacer que funcione, probablemente sería una de las mejores opciones. Traté de resolverlo pero no entiendo tu solución. - TolMera

@TolMera fijo. - petimetre

Aquí viene la versión mejorada y recursiva de la solución de AgileJon (manifestación):

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 profundidades diferentes.

Respondido 23 Feb 16, 20:02

ECMAScript-2017, que acaba de finalizar hace un mes, presenta Object.values ​​(). Entonces ahora puedes hacer esto:

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

Respondido el 24 de Septiembre de 17 a las 02:09

Creo que vale la pena señalar que jQuery soluciona esto muy bien con $.each().

Ver: .cada()

Ejemplo:

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

$(this) siendo el único elemento dentro del objeto. Intercambio $('.foo') a una variable si no desea utilizar el motor de selección de jQuery.

respondido 09 nov., 20:14

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

Para recorrer el objeto JavaScript podemos usar forEach y para optimizar el código podemos usar la función de flecha

respondido 28 nov., 18:08

No pude conseguir que las publicaciones anteriores hicieran 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

Respondido 09 ago 16, 15:08

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

Respondido 22 ago 18, 04:08

Exótico - travesía profunda

JSON.stringify(validation_messages,(field,value)=>{
  if(!field) return value;
  
  // ... your code
  
  return value;
})

En esta solución utilizamos reemplazar que permite atravesar en profundidad todo el objeto y los objetos anidados: en cada nivel obtendrá todos los campos y valores. Si necesitas llenarte camino a cada campo mira aquí

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar",
        "deep": {
          "color": "red",
          "size": "10px"
        }
    }
}

JSON.stringify(validation_messages,(field,value)=>{
  if(!field) return value;
  
  console.log(`key: ${field.padEnd(11)} - value: ${value}`);
  
  return value;
})

Respondido el 20 de junio de 20 a las 10:06

Usar ES8 Object.entries () debería ser una forma más compacta de lograr esto.

Object.entries(validation_messages).map(([key,object]) => {

    alert(`Looping through key : ${key}`);

    Object.entries(object).map(([token, value]) => {
        alert(`${token} : ${value}`);
    });
});

Respondido el 19 de junio de 20 a las 08:06

Esta solución ya fue propuesta en el otra respuesta. - sergey shubin

en 2020 quieres funciones inmutables y universales

Esto recorre su objeto multidimensional compuesto de subobjetos, matrices y cadenas y aplica una función personalizada

export const iterate = (object, func) => {
  const entries = Object.entries(object).map(([key, value]) =>
    Array.isArray(value)
      ? [key, value.map(e => iterate(e, func))]
      : typeof value === 'object'
      ? [key, iterate(value, func)]
      : [key, func(value)]
  );
  return Object.fromEntries(entries);
};

uso:

const r = iterate(data, e=>'converted_'+e);
console.log(r);

Respondido 06 Jul 20, 04:07

paraCada2

( encontró aquí):

var lunch = {
    sandwich: 'ham',
    age: 48,
};
lunch.forEach2(function (item, key) {
    console.log(key);
    console.log(item);
});

Código:

if (!Object.prototype.forEach2) {
    Object.defineProperty(Object.prototype, 'forEach2', {
        value: function (callback, thisArg) {
            if (this == null) {
                throw new TypeError('Not an object');
            }
            thisArg = thisArg || window;
            for (var key in this) {
                if (this.hasOwnProperty(key)) {
                    callback.call(thisArg, this[key], key, this);
                }
            }
        }
    });
}

Respondido 19 Oct 20, 09:10

En mi caso (en base a 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"]

Respondido el 24 de junio de 13 a las 16:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.