recorrer ¿Cómo hago un bucle o enumero un objeto JavaScript?




recorrer array de objetos javascript (24)

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

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

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

Tengo un objeto de JavaScript como el siguiente:

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

Ahora quiero recorrer todos los elementos p ( 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 el uso de eval .


Como es2015 se está volviendo más y más popular, estoy publicando esta respuesta que incluye el uso del generador y el iterador para iterar sin problemas entre pares [key, value] . 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 que puede encontrar en la página del desarrollador Mozilla.

Espero que haya ayudado a alguien.

EDITAR:

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

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 de MDN


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


Tienes que usar el bucle for-in

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

Por lo tanto, al usar bucles de entrada, siempre use el método hasOwnProperty 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
}

Haría esto en lugar de revisar 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");
}

a través del 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

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

De un vistazo, aquí es cómo 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 del alcance de esta pregunta, pero en 2011, ECMAScript 5.1 agregó el método forEach solo para Arrays, que básicamente creó una nueva forma mejorada para recorrer los arreglos mientras aún deja objetos no iterables con lo antiguo y confuso for loop. . Pero la parte extraña es que este nuevo método forEach no admite la break que llevó a todo tipo de otros problemas.

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

A partir de 2015, ahora contamos con una forma mejor lista para colocar en bucle (y romper) cualquier tipo de objeto (incluidos matrices y cadenas). Aquí es cómo se verá un bucle en JavaScript cuando la recomendación se convierta en una corriente:

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 esto se convierta en el nuevo estándar, el método anterior aún se puede usar, pero también hay alternativas en las bibliotecas populares o incluso en alternativas ligeras para aquellos que no están usando ninguna de estas bibliotecas.


Es interesante que las personas en estas respuestas hayan tocado tanto en Object.keys() como for...of pero nunca las han combinado:

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

No puedes solo for...of un Object porque no es un iterador, y for...index o .forEach() ing el Object.keys() es feo / ineficiente.
Me alegra que la mayoría de las personas se abstengan de for...in (con o sin verificar .hasOwnProperty() ) ya que también es un poco desordenado, así que, aparte de mi respuesta anterior, estoy aquí para decir ...

Puedes hacer iterantes las asociaciones de objetos ordinarios! Comportarse como Map s con el uso directo de la fantasía for...of
DEMO trabajando 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);

Mientras incluyas mi calza abajo:

//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 de mapa real que no tenga el azúcar sintáctico agradable.

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 todavía desea aprovechar las otras funciones de Map (sin agregarlas todas), pero aún así desea usar la notación de objetos nítidos, ya que los objetos ahora son iterables, ¡ahora puede hacer un mapa con ellos!

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

Para aquellos a los que no les guste calzar, o jugar con el prototype en general, siéntase libre de hacer la función en la ventana, llamándolo algo así como getObjIterator() entonces;

//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 puedes 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.


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>


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

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


Considerando ES6, me gustaría agregar mi propia cucharada de azúcar y brindar un enfoque más para recorrer las propiedades de los objetos.

Debido a que el objeto JS simple no es iterable , no podemos utilizar el for..ofbucle para iterar sobre su contenido. Pero nadie puede detenernos para hacerlo iterable .

Tengamos 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 generators ES6 , puede hacer que el código de arriba 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 a todos los objetos con Objectiterable en el prototypenivel.

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

Además, los objetos que cumplen con el protocolo iterable pueden usarse con el nuevo operador de spread características ES2015, spread 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 puedes usar la tarea de destructuring :

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

Puedes revisar JSFiddle con todo el código que he proporcionado anteriormente.


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

let arrValues = Object.values( yourObject) ;

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

MDN DOCS Object.values ​​()

y para las llaves (ya contestadas antes que yo aquí)

let arrKeys   = Object.keys(yourObject);

Puedes iterar sobre él como:

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

Tenga en cuenta que la key no asumirá el valor de la propiedad, es solo un valor de índice.


Tuve un problema similar al usar Angular, aquí está la solución que he encontrado.

Paso 1. Consigue todas las claves de objeto. utilizando Object.keys. Este método devuelve una matriz de las propias propiedades enumerables de un objeto dado.

Paso 2. Crea una matriz vacía. Aquí es donde todas las propiedades van a vivir, ya que su nuevo bucle ngFor va a apuntar a esta matriz, tenemos que capturarlas todas. Paso 3. Iterar lanza todas las claves y empuja cada una en la matriz que creaste. Así es como se ve en el código.

    // Evil response in a variable. Here are all my vehicles.
let evilResponse = { 
  "car" : 
    { 
       "color" : "red",
       "model" : "2013"
    },
   "motorcycle": 
    { 
       "color" : "red",
       "model" : "2016"
    },
   "bicycle": 
    { 
       "color" : "red",
       "model" : "2011"
    }
}
// Step 1. Get all the object keys.
let evilResponseProps = Object.keys(evilResponse);
// Step 2. Create an empty array.
let goodResponse = [];
// Step 3. Iterate throw all keys.
for (prop of evilResponseProps) { 
    goodResponse.push(evilResponseProps[prop]);
}

Aquí hay un enlace a la publicación original. https://medium.com/@papaponmx/looping-over-object-properties-with-ngfor-in-angular-869cd7b2ddcc


Puede agregar una función simple de ForEach a todos los objetos, por lo que puede 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, usted puede simplemente llamar:

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

Si no desea obtener conflictos con otros métodos de Each, puede asignarle un nombre exclusivo.


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
}

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

Nota: puede hacer esto sobre matrices, pero también recorrerá la length y otras propiedades.


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

ES6 añade for...of :

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

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

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

Tanto Object.keys() como Object.entries() propiedades en el mismo orden que for...in loop pero ignoran la cadena del prototipo . Solo se iteran las propias propiedades enumerables del objeto.

Edit: ES2016 → ES6


En ES6 tenemos símbolos conocidos para exponer algunos métodos internos previamente, 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 al utilizar for ... in es6 loop.

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

¡Pero es importante saber las capacidades que ahora tiene usando es6!


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


Un objeto se convierte en un iterador cuando implementa el método .next ()

const james = {
name: 'James',
height: `5'10"`,
weight: 185,

[Symbol.iterator]() {
let properties = []
for (let key of Object.keys(james)){
     properties.push(key);
 }

index = 0;
return {
        next: () => {
            let key = properties[index];
            let value = this[key];
            let done = index >= properties.length - 1 ;
            index++;
            return { key, value, done };
        }
    };
  }

};


const iterator = james[Symbol.iterator]();

console.log(iterator.next().value); // 'James'
console.log(iterator.next().value); // `5'10`
console.log(iterator.next().value); // 185

Object.keys (obj): Array

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

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 se Object.keys( obj ).forEach(function( key ){}) que Object.keys( obj ).forEach(function( key ){}) es más rápido. 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.
  • para ... en / hasOwnProperty enfoque 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 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);
});


Puede usar el bucle for-in 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]);
    }
}


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




each