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

Tanmoy
fuente
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}`);
}
levik
fuente
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.

Axel Rauschmayer
fuente
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
}
Andreas Grech
fuente
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.

Visión
fuente
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

Pencroff
fuente
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:

TJ Crowder
fuente
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.

Bryan
fuente
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

FieryCod
fuente
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.

Richard Levasseur
fuente
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]
}
Francis Lewis
fuente
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
strider
fuente
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.

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

Dmitry Sheiko
fuente
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]) })

Patel áspero
fuente
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>

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

Onera
fuente
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
}
mohamed-ibrahim
fuente
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]))

George Bailey
fuente
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í

Kamil Kiełczewski
fuente
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.

Biber
fuente
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.

Nicolas Bouvrette
fuente
¿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!

Bamieh
fuente
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");
}
Luis
fuente
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]);
        }
    }
}

senthil
fuente
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])
}
Nicolas Cabanas
fuente
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/>');
});

Dheeraj Vepakomma
fuente
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");
      }
   }
}

Tadas V.
fuente
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.

Artyom Pranovich
fuente
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);
yehonatan yehezkel
fuente
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);
}

Ankit
fuente