¿Cómo recorro o enumero un objeto JavaScript?


2882

Tengo un objeto JavaScript como el siguiente:

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

Ahora quiero recorrer todo p los 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 usareval .


99
Cambié JSON a JavaScript (objeto) para evitar la confusión de los literales de objetos y JSON.
Felix Kling

Respuestas:


4371

Puede usar el for-inbucle como lo muestran otros. Sin embargo, también debe asegurarse de que la clave que obtiene es una propiedad real de un objeto y no proviene 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 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 propiedades con nombre, yObject.keys() garantiza el uso de solo las propiedades propias del objeto sin las propiedades completas de la cadena del prototipo.

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 antiguos.

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

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}

34
Le propondría que cambiara la línea de alerta solo por claridadalert(key + " -> " + JSON.stringify(p[key]));
Steve Midgley

80
¿Puedes explicar la necesidad de hasOwnProperty? ¿Qué quieres decir con prototipo?
kamaci

331
En javascript, cada objeto tiene un par de pares clave-valor integrados que tienen metainformación. Cuando recorre todos los pares clave-valor de un objeto, también lo recorre. hasOwnPropery () los filtra.
danieltalsky

57
En realidad, For ... in no está en desuso. Para cada ... en es. Pero realmente me gusta el término arqueólogos ... Voy a tener que comenzar a usar eso.
Ben Y

17
cada objeto en javascript (en realidad un par clave-valor) tiene una propiedad llamada __proto__o prototype. Esta propiedad tiene una referencia a su objeto padre. Un objeto hereda automáticamente la propiedad de su padre. Esta es la razón del uso hasOwnProperty, lo que significa que estamos interesados ​​en los objetos de propiedad propia y no en los primarios.
Zubair Alam

1104

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 Object.entries()que evita tener que buscar cada valor en el objeto original:

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

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

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

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


21
¿Por qué no 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.
David Harkness

77
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness

77
@DavidHarkness Hay Object.entries en ES2017. Allí puede hacer lo siguiente: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([clave, valor] es la desestructuración de la matriz, para acceder a ambos elementos directamente. Y tiene que ajustar los parámetros en parens adicionales.)
Andreas Linnert

¿Cómo obtengo indexla clave en json? ¿O si fuera necesario, debería usar un contador separado?
Saravanabalagi Ramachandran

3
for...ofes el estándar ES6, no ES2016.
Rax Weber

342

Tienes que usar el bucle for-in

Pero tenga mucho cuidado al usar este tipo de bucle, porque esto hará un bucle de 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á revisando:

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
}

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 perdería los soportes alrededor de la continuación; Son superfluos.
SystemicPlural

52
No eliminaría { }personalmente porque ifsin ellos, no queda claro qué es parte de iflo que no es. Pero supongo que es solo una cuestión de opinión :)
pimvdb 05 de

34
Sí, prefiero mantenerlo { }principalmente para evitar confusiones si más adelante uno necesita agregar algo al ifalcance.
Andreas Grech

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 un alcance de función. Entonces, lo que realmente quise decir fue "if block".
Andreas Grech

1
eomeroff, si estás realmente preocupado por eso, siempre puedes hacer algo como: Object.prototype.hasOwnProperty.call(p, prop) Sin embargo, esto tampoco puede proteger contra las manipulaciones del prototipo de Object ...
jordancpaul

252

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

Hoy en día, muchas bibliotecas 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 usar para iterar sin problemas sobre objetos y matrices:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. En Underscore.js puedes encontrar el método_.each() , que itera sobre una lista de elementos, dando a cada uno 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 los objetos como las matrices, sin embargo (!) Los objetos con lengthpropiedad se tratan como matrices, y para evitar este comportamiento se sugiere usar_.forIn()_.forOwn() métodos y métodos (estos también tienen valueargumentos en primer lugar):

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

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

En general, todos los métodos descritos tienen el mismo comportamiento con cualquier objeto suministrado. Además de usar el for..inciclo nativo , generalmente 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.


44
Para llegar al valor: $ .each (obj, function (key, value) {console.log (value.title);});
Ravi Ram

2
Es curioso cómo subrayaron y jquery cambiaron los parámetros :)
ppasler

52

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

Más información que puedes 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 de navegador que puede ver en la tabla de compatibilidad de Kangax

Para el navegador antiguo, tiene un 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


De hecho, solo quería publicar este método. Pero me
ganaste

50

Prefacio:

  • Las propiedades del objeto pueden ser propias (la propiedad está en el objeto mismo) o heredadas (no en el objeto mismo, 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 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 , spec ]: una 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 ]: una 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 sea que esos nombres sean cadenas 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:

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

Object.values:

Object.entries:

Object.getOwnPropertyNames:

Object.getOwnPropertySymbols:

Reflect.ownKeys:

Todas las propiedades , incluidas las heredadas no enumerables:


Buena adición de propiedades de objetos enumerables / no enumerables.
serraosays

49

Puedes 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.


13
Esto se repite y ni siquiera es completamente correcto. Debe hacer una comprobación de hasOwnProperty para que esto funcione correctamente
Vatsal

44
Inicialmente rechacé esto basado en el comentario anterior hasta que me di cuenta de que esta respuesta vino primero, por lo tanto, no se "repite". Posiblemente esté incompleto, pero funciona bien en muchos casos.
billynoah

27

Como es2015 se está volviendo cada vez más popular, estoy publicando esta respuesta que incluye el uso del generador y el iterador para iterar suavemente 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 puede hacer un iterador y un generador puede encontrarla en la página del desarrollador Mozilla.

Espero que haya ayudado a alguien.

EDITAR:

ES2017 incluirá lo Object.entriesque hará que la iteración sobre [key, value]pares en objetos sea aún más fácil. Ahora se sabe que será parte de un estándar según el ts39 información de la etapa .

Creo que es hora de actualizar mi respuesta para que se vuelva 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


Esto me parece totalmente superfluo / innecesario. ¿Lo agregarías a cada objeto en tu sistema? Pensé que el punto de proporcionar un iterador era para que pudieras hacer `for (const [k, v] of myObject) '. Simplemente parece un código extra que proporciona poco valor adicional.
Dean Radcliffe

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

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


44
Cuando se utiliza un bucle for como ese, keysolo tomará un valor de índice, por lo que solo alertará a 0, 1, 2, etc ... Debe acceder a p [clave].
Bryan

1
Es el método más lento de iteración de matriz en JavaScript. Puede verificar esto en su computadora - La mejor manera de iterar sobre matrices en JavaScript
Pencroff

55
@Pencroff: el problema es que la pregunta no se trata de recorrer los arreglos ...;)
Sk8erPeter

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 ); }está apareciendo "p1" y "p2" en las alertas, ¿qué tiene de malo eso?
Sebastian

55
Creo que la principal diferencia es la calidad: las otras respuestas no solo dicen cómo, sino también 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 :).
Richard Levasseur

20

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 javascript adicional. Esto es todo lo que estoy usando:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}

18
Si el objeto JSON está limpio o no es irrelevante. Si en algún otro momento algún código establece una propiedad Object.prototype, entonces será enumerado por for..in. Si está seguro de que no está utilizando ninguna biblioteca que lo haga, no necesita llamar hasOwnProperty.
G-Wiz

44
Puede estar completamente limpio si se crea conObject.create(null)
Juan Mendes

20

a través de un prototipo con forEach () que debe 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

2
Tenga 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.
David Harkness

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 las personas se abstengan for...in(con o sin verificación .hasOwnProperty()), ya que eso también es un poco desordenado, por lo que, aparte de mi respuesta anterior, estoy aquí para decir ...


¡Puedes hacer que las asociaciones de objetos ordinarios se repitan! 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 incluyas mi cuña 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 agradable azúcar sintáctico.

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

De hecho, con esta cuña, si aún desea aprovechar la otra funcionalidad de Map (sin calzarlas todas) pero aún desea 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éntanse libres 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 solo 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 razón para que eso no funcione.

Bienvenido al futuro.


1
Caso en punto . Mientras la gente se desplace hacia abajo y lo encuentre ú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, termine descubriéndolo y luego vuelvo a compartir. Es un buen doco, ¡he encontrado mis propias respuestas antes de buscar en Google cosas que olvidé por completo!
Hashbrown

@HelpMeStackOverflowMyOnlyHope Personalmente, no me gusta modificar los prototipos de objetos que no definí.
Janus Troelsen

@JanusTroelsen ¿Leíste toda la respuesta? 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;
Hashbrown

Tenga en cuenta que esta técnica no funciona en objetos simples, pero no obstante es útil.
noɥʇʎԀʎzɐɹƆ

funciona para objetos simples, ese es literalmente el punto completo (así como los nombres de las variables como ordinaryObjectpara enfatizar que la magia aún funciona para esos tipos). ¿Revisaste las demos? ¿Qué no te funciona, @ noɥʇʎԀʎzɐɹƆ? (PD: tu imagen de perfil de SE es jefe)
Hashbrown

13

Object.keys (obj): Array

recupera todas las claves con valores de cadena de todas las propiedades enumerables propias (no heredadas).

Por lo tanto, proporciona la misma lista de claves que pretendía 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ápido. Probémoslo:

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 Object.keys tomó 40.21101451665163 milisegundos.
  • para ... en / hasOwnProperty el enfoque tomó 98.26163508463651 milisegundos.

PD. en Chrome la diferencia aún más grande http://codepen.io/dsheiko/pen/JdrqXa

PS2: en ES6 (EcmaScript 2015) puede iterar mejor el objeto iterable:

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


si no desea dejar de lado la notación {}, aún puede usarla of sin crear Maps
Hashbrown

13

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


3
Esto es bastante bueno, sin embargo, para objetos grandes, el formétodo podría ser más eficaz.
Rolf

13

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>


12

También puede usar Object.keys () e iterar sobre las teclas de objeto como 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]);
});


Me ahorraste tiempo, gracias
Swap-IOS-Android

Feliz de saber :)
Onera

8

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
}

8

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

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

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


8

Actuación

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 de objetos grandes y pequeños
  • Sorprendentemente, la for-ofsolución (H) es rápida en Chrome para objetos pequeños y grandes
  • soluciones basadas en índice explícito i (J, K) son bastante rápidas en todos los navegadores para objetos pequeños (para Firefox también es rápido para objetos grandes pero medio rápido en otros navegadores)
  • Las soluciones basadas en iteradores (D, E) son más lentas y no se recomiendan
  • la solución C es lenta para objetos grandes y medianamente 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 pruebas en su máquina AQUÍ
  • objeto 'grande' - con 1000 campos - puede realizar pruebas en su máquina AQUÍ

A continuación, los fragmentos presentan soluciones usadas

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

ingrese la descripción de la imagen aquí


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 llamar simple:

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

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


3
La modificación de los prototipos de objetos integrados (como Object) generalmente se considera un antipatrón porque puede causar fácilmente conflictos con otro código. Así que no recomiendo hacerlo de esta manera.
Moritz

6

Los bucles pueden ser bastante interesantes cuando se usa JavaScript puro. Parece que solo ECMA6 (nueva especificación JavaScript 2015) tiene los bucles bajo control. Desafortunadamente, mientras escribo esto, los navegadores y el popular entorno de desarrollo integrado (IDE) todavía están luchando para soportar completamente las nuevas campanas y silbatos.

De un vistazo, aquí se ve un bucle de objetos 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 de alcance con esta pregunta, pero en 2011, ECMAScript 5.1 agregó el forEachmétodo solo para matrices, que básicamente creó una nueva forma mejorada de recorrer las matrices y al mismo tiempo dejar objetos no iterables con el antiguo forciclo detallado y confuso . Pero la parte extraña es que este nuevo forEachmétodo no es compatible, lo breakque condujo a todo tipo de problemas.

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

A partir de 2015, ahora tenemos una mejor manera de hacer 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 este indicador especial para que funcione: chrome://flags/#enable-javascript-harmony

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


¿Podría proporcionar un violín de este trabajo? Aquí está mi intento. jsfiddle.net/abalter/sceeb211
abalter

@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
Nicolas Bouvrette

Estoy en Chrome y obteniendo Uncaught TypeError: Object.entries is not a function. ¿Todavía no está implementado en Chrome?
abalter

@abalter lo es. Asegúrese de tener Chrome versión 51 y de haber habilitado el indicador como se explica en mis comentarios de edición y Jsfiddle. Puede consultar los detalles aquí: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nicolas Bouvrette

Lo siento, me perdí eso de la bandera. Veo que aún no es una característica completamente implementada.
abalter

5

En ES6 tenemos símbolos bien conocidos para exponer algunos métodos internos anteriores, puede 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 usando es6!


1
Un iterador de objeto personalizado llama al iterador de matriz incorporado de una matriz que se genera Object.keys()y se asigna en la memoria ... ¡Genial!
ooo

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

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


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]); } } }
Marek Bernád

5

Usando un for-ofencendidoObject.keys()

Me gusta:

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

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

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) encontradas directamente sobre 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/>');
});


2
Esto es fantástico, gracias por publicar esta respuesta. Necesitaba introspectar 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 las Errorque no podía acceder antes. ¡Gracias!
Pierce

4

Si alguien necesita recorrer los objetos de matriz con condición :

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];

for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  
  for(key in arrayObjects[i]) {      
    
      if (key == "status" && arrayObjects[i][key] == "good") {
        
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}


4

Considerando ES6, me gustaría agregar mi propia cucharada de azúcar y proporcionar un enfoque más para iterar sobre las propiedades del objeto.

Dado que el objeto JS simple no es iterable de fábrica, no podemos usar el for..ofbucle para iterar sobre su contenido. Pero nadie puede detenernos para que sea iterable .

Vamos a tener bookobjeto.

let book = {
  title: "Amazing book",
  author: "Me",
  pages: 3
}

book[Symbol.iterator] = function(){

  let properties = Object.keys(this); // returns an array with property names
  let counter = 0;
  let isDone = false;

  let next = () => {
    if(counter >= properties.length){
      isDone = true;
    }
    return { done: isDone, value: this[properties[counter++]] }
  }

  return { next };
}

Como lo hemos hecho, podemos usarlo de esta manera:

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3

O si conoce el poder de los generadores ES6 , entonces ciertamente puede hacer que el código anterior sea mucho más corto.

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

Claro, puede aplicar dicho comportamiento para todos los objetos haciendo que sea Objectiterable en el prototypenivel.

Object.prototype[Symbol.iterator] = function() {...}

Además, los objetos que cumplen con el protocolo iterable se pueden usar con el nuevo operador de propagación de características ES2015, por lo que podemos leer los valores de las propiedades de los objetos como una matriz.

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]

O puede usar la asignación de desestructuración :

let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3

Puede consultar JSFiddle con todo el código que he proporcionado anteriormente.


Encontré que el código generará los valores pero sin claves. ¿Es posible iterar los valores con claves?
Pika

Sí tu puedes. Simplemente devuelva "rendir [clave, obj [clave]];" desde su función de generador y luego
úsela

4

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

let arrValues = Object.values( yourObject) ;

¡devuelve una matriz de valores de objetos y no extrae valores de Prototype!

MDN DOCS Object.values ​​()

y para llaves (ya respondí antes que yo aquí)

let arrKeys   = Object.keys(yourObject);

Las respuestas piden una solución que devuelva claves y valores.
Sean Lindo

4

En la última secuencia de comandos ES, puede hacer algo como esto:

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, value);
}

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.