¿Cómo recorro o enumero un objeto JavaScript?

3244

Tengo un objeto JavaScript como el siguiente:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Ahora quiero recorrer todos plos elementos ( p1, p2, p3...) y obtener sus claves y valores. ¿Cómo puedo hacer eso?

Puedo modificar el objeto JavaScript si es necesario. Mi objetivo final es recorrer algunos pares de valores clave y, si es posible, quiero evitar usarlos eval.

0
4819

Puede usar el for-inbucle como lo muestran otros. Sin embargo, también debe asegurarse de que la clave que obtenga sea una propiedad real de un objeto y no provenga del prototipo.

Aquí está el fragmento:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

Alternativa de For-of con Object.keys ():

var p = {
    0: "value1",
    "b": "value2",
    key: "value3"
};

for (var key of Object.keys(p)) {
    console.log(key + " -> " + p[key])
}

Observe el uso de en for-oflugar de for-in, si no se usa, devolverá indefinido en las propiedades nombradas y Object.keys()asegura el uso de solo las propiedades propias del objeto sin todas las propiedades de la cadena de prototipos

Usando el nuevo Object.entries()método:

Nota: Internet Explorer no admite este método de forma nativa. Puede considerar usar un Polyfill para navegadores más antiguos.

const p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}
2
  • 369
    En javascript, cada objeto tiene un montón de pares clave-valor incorporados que tienen metainformación. Cuando recorre todos los pares clave-valor de un objeto, también los está recorriendo. hasOwnPropery () los filtra. 27/01/12 a las 15:56
  • 66
    En realidad, For ... in no está desaprobado. Para cada ... en es. Pero me gusta mucho el término arqueólogos ... tendré que empezar a usarlo.
    Ben Y
    27 feb 2014 a las 16:08
1231

En ECMAScript 5, puede combinar Object.keys()y Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ECMAScript 6 agrega for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ECMAScript 8 agrega lo Object.entries()que evita tener que buscar cada valor en el objeto original:

Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

Puede combinar for...of, desestructurar y Object.entries:

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

Ambos Object.keys()e Object.entries()iteran propiedades en el mismo orden que un for...inbucle, pero ignoran la cadena del prototipo . Solo se iteran las propiedades enumerables propias del objeto.

1
  • 23
    ¿Por qué no lo proporcionó el estándar Object.forEach(obj, function (value, key) {...})? :( Ciertamente obj.forEach(function...)sería más corto y complementario Array.prototype.forEach, pero eso correría el riesgo de que los objetos definan su propia forEachpropiedad. Supongo que Object.keysprotege contra la devolución de llamada que modifica las claves del objeto. 23/06/2014 a las 20:36
359

Tienes que usar el bucle for-in

Pero tenga mucho cuidado al usar este tipo de bucle, ya que esto repetirá todas las propiedades a lo largo de la cadena del prototipo .

Por lo tanto, cuando use bucles for-in, siempre use el hasOwnPropertymétodo para determinar si la propiedad actual en iteración es realmente una propiedad del objeto que está verificando:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}
5
  • 31
    Esto es mejor que la solución de levik porque permite que la lógica principal sea solo un bucle anidado en lugar de dos; facilitando la lectura del código. Aunque soltaría los corchetes alrededor de la continuación; son superfluos. 6/04/11 a las 9:55
  • 53
    No eliminaría los { }personalmente porque ifsin ellos hace que sea un poco confuso qué es parte del ify qué no. Pero supongo que es solo una cuestión de opinión :)
    pimvdb
    5 de agosto de 2011 a las 12:01
  • 34
    Sí, prefiero mantener el { }principalmente para evitar confusiones si luego se necesita agregar algo al ifalcance. 5 de agosto de 2011 a las 12:21
  • 8
    Al leer mi comentario anterior, me di cuenta de que no usaba los términos correctos, porque dije "si alcance"; pero tenga en cuenta que JavaScript solo tiene alcance de función. Entonces, lo que en realidad quise decir fue "si bloquear". 11/11/11 a las 11:08
  • "Desafortunadamente, hasOwnProperty es un método, no un operador, por lo que en cualquier objeto podría ser reemplazado por una función diferente o incluso por un valor que no sea una función" 19 de junio de 2013 a las 8:56
260

La pregunta no estará completa si no mencionamos métodos alternativos para recorrer objetos.

Hoy en día, muchas bibliotecas de JavaScript conocidas proporcionan sus propios métodos para iterar sobre colecciones, es decir, sobre matrices , objetos y objetos similares a matrices . Estos métodos son convenientes de usar y son totalmente compatibles con cualquier navegador.

  1. Si trabaja con jQuery , puede usar el jQuery.each()método. Se puede utilizar para iterar sin problemas sobre objetos y matrices:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
    
  2. En Underscore.js puede encontrar el método _.each(), que itera sobre una lista de elementos, dando cada uno a su vez a una función proporcionada (¡preste atención al orden de los argumentos en la función iteratee !):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
    
  3. Lo-Dash proporciona varios métodos para iterar sobre las propiedades del objeto. Basic _.forEach()(o su alias _.each()) es útil para recorrer tanto objetos como matrices, sin embargo (!) Los objetos con lengthpropiedad se tratan como matrices, y para evitar este comportamiento, se sugiere usar métodos _.forIn()y _.forOwn()(estos también tienen valueargumentos en primer lugar):

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });
    

    _.forIn()itera sobre las propiedades enumerables propias y heredadas de un objeto, mientras que _.forOwn()itera solo sobre las propiedades propias de un objeto (básicamente contrastando la hasOwnPropertyfunción). Para objetos simples y literales de objeto, cualquiera de estos métodos funcionará bien.

Generalmente, todos los métodos descritos tienen el mismo comportamiento con cualquier objeto proporcionado. Además, el uso de un for..inbucle nativo suele ser más rápido que cualquier abstracción, por ejemplo jQuery.each(), estos métodos son considerablemente más fáciles de usar, requieren menos codificación y proporcionan un mejor manejo de errores.

2
  • 4
    Para llegar al valor: $ .each (obj, function (key, value) {console.log (value.title);}); 8 de junio de 2013 a las 14:41
  • 2
    Es curioso cómo el subrayado y jquery cambiaron los parámetros :)
    ppasler
    8 de septiembre de 2017 a las 7:24
62

Prefacio:

  • Las propiedades del objeto pueden ser propias (la propiedad está en el objeto en sí) o heredadas (no en el objeto en sí, en uno de sus prototipos).
  • Las propiedades del objeto pueden ser enumerables o no enumerables . Las propiedades no enumerables quedan fuera de muchas enumeraciones / matrices de propiedades.
  • Los nombres de propiedad pueden ser cadenas o símbolos. Las propiedades cuyos nombres son Símbolos quedan fuera de muchas enumeraciones / matrices de propiedades.

Aquí en 2018, sus opciones para recorrer las propiedades de un objeto son (algunos ejemplos siguen a la lista):

  1. for-in[ MDN , spec ]: una estructura de bucle que recorre los nombres de las propiedades enumerables de un objeto , incluidas las heredadas, cuyos nombres son cadenas
  2. Object.keys[ MDN , spec ] - Una función de proporcionar una matriz de los nombres de los de un objeto propias , enumerables propiedades cuyos nombres son cadenas.
  3. Object.values[ MDN , spec ] - Una función de proporcionar una matriz de los valores de de un objeto propias , enumerables propiedades.
  4. Object.entries[ MDN , spec ] - Una función de proporcionar una matriz de los nombres y valores de de un objeto propias , enumerables propiedades (cada entrada de la matriz es una [name, value]matriz).
  5. Object.getOwnPropertyNames[ MDN , especificación ]: función que proporciona una matriz de los nombres de las propiedades propias de un objeto (incluso las no enumerables) cuyos nombres son cadenas.
  6. Object.getOwnPropertySymbols[ MDN , spec ]: función que proporciona una matriz de los nombres de las propiedades propias de un objeto (incluso las no enumerables) cuyos nombres son símbolos.
  7. Reflect.ownKeys[ MDN , spec ]: una función que proporciona una matriz de los nombres de las propiedades propias de un objeto (incluso las no enumerables), ya sean cadenas de caracteres o símbolos.
  8. Si desea que todas las propiedades de un objeto, incluyendo las heredadas no enumerables, es necesario utilizar un bucle y Object.getPrototypeOf[ MDN , spec ] y el uso Object.getOwnPropertyNames, Object.getOwnPropertySymbolso Reflect.ownKeysen cada objeto en la cadena de prototipo (ejemplo en la parte inferior de esta respuesta).

Con todos ellos, excepto for-in, que tendría que utilizar algún tipo de bucle construcción de la matriz ( for, for-of, forEach, etc.).

Ejemplos:

for-in:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name in o) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.keys (con un for-ofbucle, pero puede usar cualquier construcción de bucle) :

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.keys(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.values:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const value of Object.values(o)) {
    console.log(`${value}`);
}

Object.entries:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const [name, value] of Object.entries(o)) {
    console.log(`${name} = ${value}`);
}

Object.getOwnPropertyNames:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertyNames(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.getOwnPropertySymbols:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertySymbols(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}

Reflect.ownKeys:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Reflect.ownKeys(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}

Todas las propiedades , incluidas las heredadas no enumerables:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (let depth = 0, current = o; current; ++depth, current = Object.getPrototypeOf(current)) {
    for (const name of Reflect.ownKeys(current)) {
        const value = o[name];
        console.log(`[${depth}] ${String(name)} = ${String(value)}`);
    }
}
.as-console-wrapper {
  max-height: 100% !important;
}
1
  • 1
    Buena adición de propiedades de objeto enumerables / no enumerables. 22 de abril de 2019 a las 4:46
55

En ECMAScript 5 tiene un nuevo enfoque en los campos de iteración de literal - Object.keys

Más información que puede ver en MDN

Mi elección está a continuación como una solución más rápida en las versiones actuales de los navegadores (Chrome30, IE10, FF25)

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Puede comparar el rendimiento de este enfoque con diferentes implementaciones en jsperf.com :

Soporte del navegador que puede ver en la tabla de compatibilidad de Kangax

Para el navegador antiguo, tiene polyfill simple y completo

UPD:

comparación de rendimiento para todos los casos más populares en esta pregunta sobre perfjs.info:

iteración literal de objeto

1
  • 1
    De hecho, solo quería publicar este método. Pero me ganaste :( 20 de marzo de 2014 a las 23:05
54

Puede simplemente iterar sobre él como:

for (var key in p) {
  alert(p[key]);
}

Tenga en cuenta que keyno tomará el valor de la propiedad, es solo un valor de índice.

2
  • 14
    Esto se repite y ni siquiera es del todo correcto. Necesita tener una verificación de hasOwnProperty para que esto funcione correctamente
    Vatsal
    2/06/2016 a las 20:18
  • 4
    Inicialmente voté en contra de esto basado en el comentario anterior hasta que me di cuenta de que esta respuesta fue la primera, por lo tanto, no se "repite". Es posible que esté incompleto, pero funciona bien en muchos casos. 9 oct 2018 a las 15:16
30

Dado que es2015 se está volviendo cada vez más popular, estoy publicando esta respuesta que incluye el uso del generador y el iterador para iterar sin problemas a través de [key, value]pares. Como es posible en otros idiomas, por ejemplo Ruby.

Ok, aquí hay un código:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function*() {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Toda la información sobre cómo se puede hacer un iterador y un generador se puede encontrar en la página del desarrollador de Mozilla.

Espero que haya ayudado a alguien.

EDITAR:

ES2017 incluirá Object.entrieslo que facilitará [key, value]aún más la iteración sobre pares en objetos. Ahora se sabe que será parte de un estándar de acuerdo con la información de la etapa ts39 .

Creo que es hora de actualizar mi respuesta para que sea aún más fresca de lo que es ahora.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Puede encontrar más información sobre el uso en la página MDN

1
  • Esto me parece totalmente superfluo / innecesario. ¿Lo agregaría a todos los objetos de su sistema? Pensé que el objetivo de proporcionar un iterador era para que pudieras hacer 'for (const [k, v] of myObject)'. Simplemente parece un código adicional que proporciona poco valor adicional. 28 de septiembre de 2017 a las 16:36
29

Rendimiento

Hoy 2020.03.06 realizo pruebas de las soluciones elegidas en Chrome v80.0, Safari v13.0.5 y Firefox 73.0.1 en MacOs High Sierra v10.13.6

Conclusiones

  • las soluciones basadas en for-in(A, B) son rápidas (o más rápidas) para todos los navegadores para objetos grandes y pequeños
  • sorprendentemente, la for-ofsolución (H) es rápida en cromo para objetos pequeños y grandes
  • Las soluciones basadas en índices explícitos i(J, K) son bastante rápidas en todos los navegadores para objetos pequeños (para Firefox también son rápidas para objetos grandes pero medianamente rápidas en otros navegadores)
  • las soluciones basadas en iteradores (D, E) son las más lentas y no se recomiendan
  • La solución C es lenta para objetos grandes y media-lenta para objetos pequeños.

ingrese la descripción de la imagen aquí

Detalles

Se realizaron pruebas de rendimiento para

  • objeto pequeño - con 3 campos - puede realizar la prueba en su máquina AQUÍ
  • objeto 'grande' - con 1000 campos - puede realizar la prueba en su máquina AQUÍ

A continuación, los fragmentos presentan las soluciones utilizadas.

function A(obj,s='') {
	for (let key in obj) if (obj.hasOwnProperty(key)) s+=key+'->'+obj[key] + ' ';
  return s;
}

function B(obj,s='') {
	for (let key in obj) s+=key+'->'+obj[key] + ' ';
  return s;
}

function C(obj,s='') {
  const map = new Map(Object.entries(obj));
	for (let [key,value] of map) s+=key+'->'+value + ' ';
  return s;
}

function D(obj,s='') {
  let o = { 
    ...obj,
    *[Symbol.iterator]() {
      for (const i of Object.keys(this)) yield [i, this[i]];    
    }
  }
  for (let [key,value] of o) s+=key+'->'+value + ' ';
  return s;
}

function E(obj,s='') {
  let o = { 
    ...obj,
    *[Symbol.iterator]() {yield *Object.keys(this)}
  }
  for (let key of o) s+=key+'->'+o[key] + ' ';
  return s;
}

function F(obj,s='') {
	for (let key of Object.keys(obj)) s+=key+'->'+obj[key]+' ';
  return s;
}

function G(obj,s='') {
	for (let [key, value] of Object.entries(obj)) s+=key+'->'+value+' ';
  return s;
}

function H(obj,s='') {
	for (let key of Object.getOwnPropertyNames(obj)) s+=key+'->'+obj[key]+' ';
  return s;
}

function I(obj,s='') {
	for (const key of Reflect.ownKeys(obj)) s+=key+'->'+obj[key]+' ';
  return s;
}

function J(obj,s='') {
  let keys = Object.keys(obj);
	for(let i = 0; i < keys.length; i++){
    let key = keys[i];
    s+=key+'->'+obj[key]+' ';
  }
  return s;
}

function K(obj,s='') {
  var keys = Object.keys(obj), len = keys.length, i = 0;
  while (i < len) {
    let key = keys[i];
    s+=key+'->'+obj[key]+' ';
    i += 1;
  }
  return s;
}

function L(obj,s='') {
  Object.keys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );
  return s;
}

function M(obj,s='') {
  Object.entries(obj).forEach(([key, value]) => s+=key+'->'+value+' ');
  return s;
}

function N(obj,s='') {
  Object.getOwnPropertyNames(obj).forEach(key => s+=key+'->'+obj[key]+' ');
  return s;
}

function O(obj,s='') {
  Reflect.ownKeys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );
  return s;
}



// TEST

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
let log = (name,f) => console.log(`${name} ${f(p)}`)

log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This snippet only presents choosen solutions

Y aquí están los resultados para objetos pequeños en cromo.

ingrese la descripción de la imagen aquí

28
for(key in p) {
  alert( p[key] );
}

Nota: puede hacer esto sobre matrices, pero también iterará sobre las lengthy otras propiedades.

5
  • 4
    Cuando se usa un bucle for como ese, keysolo tomará un valor de índice, por lo que solo alertará 0, 1, 2, etc. Necesita acceder a p [clave].
    Bryan
    26 de marzo de 2009 a las 6:07
  • 1
    Es el método más lento de iteración de matrices en JavaScript. Puede verificar esto en su computadora: la mejor manera de iterar sobre matrices en JavaScript 5 de diciembre de 2013 a las 12:15
  • 5
    @Pencroff: el problema es que la pregunta no se trata de recorrer matrices ...;) 1 de enero de 2014 a las 0:55
  • Esto es algo que no entiendo en stackoverflow. Richard dio la respuesta correcta, y él fue el primero en dar esa respuesta, pero ¿no obtuvo ningún +1? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }muestra "p1" y "p2" en las alertas, así que, ¿qué hay de malo en eso? 5 de agosto de 2014 a las 6:43
  • 5
    Creo que la principal diferencia es la calidad: las otras respuestas no solo dicen cómo, sino que también dicen las advertencias (por ejemplo, el prototipo) y cómo lidiar con esas advertencias. En mi humilde opinión, esas otras respuestas son mejores que las mías :). 6 de agosto de 2014 a las 16:41
21

Después de revisar todas las respuestas aquí, hasOwnProperty no es necesario para mi propio uso porque mi objeto json está limpio; Realmente no tiene sentido agregar ningún procesamiento adicional de JavaScript. Esto es todo lo que estoy usando:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}
2
  • 18
    Si el objeto JSON está limpio o no es irrelevante. Si en cualquier otro momento algún código establece una propiedad Object.prototype, entonces será enumerado por for..in. Si está seguro de que no está usando ninguna biblioteca que haga eso, entonces no necesita llamar hasOwnProperty.
    G-Wiz
    13/01/12 a las 20:15
  • 4
    Puede quedar completamente limpio si se crea con Object.create(null) 14/04/2016 a las 11:37
20

a través del prototipo con forEach () que debería omitir las propiedades de la cadena del prototipo :

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}


//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3
1
  • 2
    Cuidado con el prototipo: obj = { print: 1, each: 2, word: 3 }produce TypeError: number is not a function. Usar forEachpara igualar la Arrayfunción similar puede reducir un poco el riesgo. 23/06/14 a las 21:40
18

Es interesante que las personas en estas respuestas hayan tocado ambos Object.keys()y for...ofnunca los hayan combinado:

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

Puede no sólo for...ofuna Object, porque no es un iterador, y for...indexo .forEach()ing el Object.keys()es feo / ineficiente.
Me alegra que la mayoría de la gente se esté absteniendo de for...in(con o sin verificación .hasOwnProperty()), ya que eso también es un poco complicado, así que aparte de mi respuesta anterior, estoy aquí para decir ...


¡Puede hacer iteraciones de asociaciones de objetos ordinarios! Comportarse como Maps con el uso directo de la elegante for...of
DEMO que funciona en Chrome y FF (supongo que solo ES6)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);

//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

Siempre que incluya mi calza a continuación:

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

Sin tener que crear un objeto Map real que no tenga el atractivo sintáctico.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

De hecho, con esta corrección, si aún deseaba aprovechar la otra funcionalidad de Map (sin incluirlas todas) pero aún deseaba usar la notación de objeto ordenada, ya que los objetos ahora son iterables, ¡ahora puede hacer un mapa a partir de ella!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

Para aquellos a quienes no les gusta calzar, o meterse con ellos prototypeen general, siéntase libre de hacer la función en la ventana, llamándola así getObjIterator();

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

Ahora puede llamarlo como una función ordinaria, nada más se ve afectado

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

o

for (let pair of getObjIterator(ordinaryObject))

No hay ninguna razón por la que eso no funcione.

Bienvenido al futuro.

7
  • 2
    Caso en cuestión . Siempre que las personas se desplacen hacia abajo y lo encuentren útil, eso es todo lo que importa. Por lo general, soy yo tratando de hacer algo, sin que me gusten las cosas que veo en línea, termino descubriéndolo y luego vuelvo para compartir. Es un buen doco, ¡de hecho me encontré con mis propias respuestas antes de buscar en Google cosas que me olvidé por completo! 22 de julio de 2016 a las 6:57
  • @HelpMeStackOverflowMyOnlyHope Personalmente no me gusta modificar los prototipos de objetos que no definí yo mismo. 30 de septiembre de 2016 a las 10:19
  • @JanusTroelsen, ¿leíste la respuesta completa? For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then; 30 de septiembre de 2016 a las 12:58
  • Tenga en cuenta que esta técnica no funciona en objetos simples, pero es útil. 14/06/18 a las 15:17
  • funciona para objetos simples, ese es literalmente todo el punto (así como los nombres de las variables como ordinaryObjectpara enfatizar que la magia todavía funciona para esos tipos). ¿Revisaste las demostraciones? ¿Qué no te está funcionando, @ noɥʇʎԀʎzɐɹƆ? (PD: tu imagen de perfil de SE es la jefa) 15 de junio de 2018 a las 6:47
16

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>
0
16

También puede usar Object.keys () e iterar sobre las claves del objeto como se muestra a continuación para obtener el valor:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});
2
  • Me salvaste el tiempo, gracias 18/09/19 a las 14:39
  • Feliz de saber:)
    Onera
    26/09/19 a las 9:52
13

Object.keys(obj) : Array

retrieves all string-valued keys of all enumerable own (non-inherited) properties.

Por lo tanto, proporciona la misma lista de claves que pretende al probar cada clave de objeto con hasOwnProperty. No necesita esa operación de prueba adicional y Object.keys( obj ).forEach(function( key ){})se supone que es más rápida. Vamos a demostrarlo:

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;

// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});

// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});

p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");

// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}

p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

En mi Firefox tengo los siguientes resultados

  • El enfoque de Object.keys tomó 40.21101451665163 milisegundos.
  • for ... in / hasOwnProperty tomó 98.26163508463651 milisegundos.

PD. en Chrome la diferencia es aún mayor http://codepen.io/dsheiko/pen/JdrqXa

PS2: en ES6 (EcmaScript 2015) puede iterar un objeto iterable de forma más agradable:

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
    console.log(pair);
}

// OR 
let map = new Map([
    [false, 'no'],
    [true,  'yes'],
]);
map.forEach((value, key) => {
    console.log(key, value);
});
1
  • Si no tiene ganas de dejar de lado la notación {}, aún puede usarla of sin crear Maps 28/06/2016 a las 9:47
11

Solo código JavaScript sin dependencias:

var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p);   // ["p1", "p2", "p3"]

for(i = 0; i < keys.length; i++){
  console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
}
0
11

En el último script de ES, puede hacer algo como esto:

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, value);
}
1
  • Funciona de forma independiente, pero no funciona si esta función devuelve un valor para cada una de las condiciones. 15/09/20 a las 20:22
10

Aquí hay otro método para iterar a través de un objeto.

   var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};


Object.keys(p).forEach(key => { console.log(key, p[key]) })
1
  • 3
    Esto es bastante bueno, sin embargo, para objetos grandes, el formétodo puede ser más eficaz.
    Rolf
    10/03/18 a las 0:17
10

El uso de un for-ofsobreObject.keys()

Igual que:

let object = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
};

for (let key of Object.keys(object)) {
  console.log(key + " : " + object[key])
}
9

El Object.keys()método devuelve una matriz de las propiedades enumerables propias de un objeto dado. Leer más sobre esto aquí

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))
0
8

Múltiples formas de iterar objetos en javascript.

Usando para ... en bucle

 var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
for (let key in p){
   if(p.hasOwnProperty(key)){
     console.log(`${key} : ${p[key]}`)
   }
}

Usando para ... de bucle

 var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
for (let key of Object.keys(p)){
     console.log(`key: ${key} & value: ${p[key]}`)
}

Usando forEach () con Object.keys , Object.values , Object.entries

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
Object.keys(p).forEach(key=>{
   console.log(`${key} : ${p[key]}`);
});
Object.values(p).forEach(value=>{
   console.log(value);
});
Object.entries(p).forEach(([key,value])=>{
    console.log(`${key}:${value}`)
})
7

Puede agregar una función forEach simple a todos los objetos, para que pueda recorrer automáticamente cualquier objeto:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        for (var key in this) {
            if (!this.hasOwnProperty(key)) {
                // skip loop if the property is from prototype
                continue;
            }
            var value = this[key];
            func(key, value);
        }
    },
    enumerable: false
});

Para aquellas personas a las que no les gusta el método " para ... en ":

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        var arr = Object.keys(this);
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i];
            func(key, this[key]);
        }
    },
    enumerable: false
});

Ahora, puede simplemente llamar a:

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});

Si no desea tener conflictos con otros métodos forEach, puede nombrarlo con su nombre único.

1
  • 3
    La modificación de los prototipos de objetos incorporados (como Object) generalmente se considera un patrón anti porque puede causar fácilmente conflictos con otro código. Así que no recomiendo hacerlo de esta manera.
    Moritz
    6 de ene. De 2017 a las 13:06
6

Los bucles pueden ser bastante interesantes cuando se usa JavaScript puro. Parece que solo ECMA6 (Nueva especificación de JavaScript de 2015) logró controlar los bucles. Desafortunadamente, mientras escribo esto, tanto los navegadores como el popular entorno de desarrollo integrado (IDE) todavía están luchando para admitir completamente las nuevas campanas y silbidos.

De un vistazo, este es el aspecto de un bucle de objetos de JavaScript antes de ECMA6:

for (var key in object) {
  if (p.hasOwnProperty(key)) {
    var value = object[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
  }
}

Además, sé que esto está fuera del alcance con esta pregunta, pero en 2011, ECMAScript 5.1 agregó el forEachmétodo solo para matrices, lo que básicamente creó una nueva forma mejorada de recorrer las matrices mientras deja los objetos no iterables con el antiguo forbucle detallado y confuso . Pero lo curioso es que este nuevo forEachmétodo no es compatible, lo breakque dio lugar a todo tipo de problemas.

Básicamente, en 2011, no hay una forma realmente sólida de bucle en JavaScript que no sea la que muchas bibliotecas populares (jQuery, Underscore, etc.) decidieron volver a implementar.

A partir de 2015, ahora tenemos una forma mejor lista para usar para realizar un bucle (y romper) cualquier tipo de objeto (incluidas matrices y cadenas). Así es como se verá un bucle en JavaScript cuando la recomendación se convierta en la corriente principal:

for (let [key, value] of Object.entries(object)) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

Tenga en cuenta que la mayoría de los navegadores no admitirán el código anterior a partir del 18 de junio de 2016. Incluso en Chrome, debe habilitar esta marca especial para que funcione: chrome://flags/#enable-javascript-harmony

Hasta que esto se convierta en el nuevo estándar, el método anterior todavía se puede usar, pero también hay alternativas en bibliotecas populares o incluso alternativas ligeras para aquellos que no están usando ninguna de estas bibliotecas.

8
  • ¿Podrías darme un poco de este trabajo? Aquí está mi intento. jsfiddle.net/abalter/sceeb211
    abalter
    18/06/2016 a las 6:24
  • @abalter Lo siento, me di cuenta de que tenía un error tipográfico en mi código. Lo arreglé y actualicé su JsFiddle aquí: jsfiddle.net/sceeb211/2 18/06/2016 a las 12:56
  • Estoy en cromo y obteniendo Uncaught TypeError: Object.entries is not a function. ¿Aún no está implementado en Chrome?
    abalter
    18/06/2016 a las 16:07
  • @abalter Lo es. Asegúrese de tener la versión 51 de Chrome y de haber habilitado la bandera como se explica en mi edición y en los comentarios de Jsfiddle. Puede consultar los detalles aquí: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 18/06/2016 a las 16:39
  • Siento haberme perdido eso de la bandera. Veo que aún no es una función completamente implementada.
    abalter
    19/06/2016 a las 5:39
6

Una buena forma de hacer un bucle en un objeto JavaScript enumerable que podría ser asombroso y común para ReactJS es usar Object.keyso Object.entriescon usar la mapfunción. como abajo:

// assume items:

const items = {
  first: { name: 'phone', price: 400 },
  second: { name: 'tv', price: 300 },
  third: { name: 'sofa', price: 250 },
};

Para realizar un bucle y mostrar alguna interfaz de usuario, ReactJSactúe como se muestra a continuación:

~~~
<div>
  {Object.entries(items).map(([key, ({ name, price })]) => (
    <div key={key}>
     <span>name: {name}</span>
     <span>price: {price}</span>
    </div>
  ))}
</div>

En realidad, utilizo la tarea de desestructuración dos veces, una para obtener keyuna para obtener namey price.

2
  • Estaba buscando exactamente esto ya que estoy trabajando con React y cómo los bucles for no funcionan en el interior <Fragment>, esta es la solución perfecta. Muchas gracias 19/08/20 a las 5:52
  • Estimado @Mob_Abominator, gracias por su dulce comentario, me alegra saber que es útil para usted. pero no entiendo how for loops don't work inside <Fragment>. ¿Sigue siendo algún problema? si es así, por favor deje una pregunta y dígame, le responderé. si no queda nada y estás bien ahora. por favor, deje un voto positivo a esta publicación mía . Gracias. 19/08/20 a las 7:32
5

En ES6 tenemos símbolos bien conocidos para exponer algunos métodos previamente internos, puedes usarlo para definir cómo funcionan los iteradores para este objeto:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};

[...p] //["p1", "p2", "p3"]

esto dará el mismo resultado que usar for ... en el bucle es6.

for(var key in p) {
    console.log(key);
}

¡Pero es importante conocer las capacidades que tiene ahora con es6!

1
  • 1
    Un iterador de objeto personalizado llama al iterador de matriz incorporado de una matriz que se generó Object.keys()y se asignó en la memoria ... ¡Genial!
    ooo
    3 de mayo de 2019 a las 5:32
5

Haría esto en lugar de verificar obj.hasOwnerPropertydentro de cada for ... inbucle.

var obj = {a : 1};
for(var key in obj){
    //obj.hasOwnProperty(key) is not needed.
    console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
    throw new Error("Please don't extend the native object");
}
5

desde ES06 puede obtener los valores de un objeto como matriz con

let arrValues = Object.values( yourObject) ;

devuelve una matriz de los valores del objeto y no extrae valores de Prototype !!

MDN DOCS Object.values ​​()

y por llaves (ya contestado aquí antes que yo)

let arrKeys   = Object.keys(yourObject);
1
  • Las respuestas piden una solución que devuelva tanto claves como valores. 21/08/18 a las 19:03
5

    var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}
1
  • json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } } 14/10/2018 a las 12:27
4

Si también desea iterar sobre propiedades no enumerables , puede usar Object.getOwnPropertyNames(obj)para devolver una matriz de todas las propiedades (enumerables o no) que se encuentran directamente en un objeto dado.

var obj = Object.create({}, {
  // non-enumerable property
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

obj.foo = 1; // enumerable property

Object.getOwnPropertyNames(obj).forEach(function (name) {
  document.write(name + ': ' + obj[name] + '<br/>');
});
1
  • 2
    Esto es fantástico, gracias por publicar esta respuesta. Necesitaba hacer una introspección de un Errorobjeto y no podía acceder a las propiedades en un bucle o una _.forIn(err)llamada. El uso Object.getOwnPropertyNames(err)me permitió acceder a todas las partes de la Errorque no podía acceder antes. ¡Gracias!
    Pierce
    11/03/2016 a las 19:49