For..In loops en JavaScript - pares de valores clave

414

Me preguntaba si hay una manera de hacer algo como un foreachbucle PHP en JavaScript. La funcionalidad que estoy buscando es algo como este fragmento de PHP:

foreach($data as $key => $value) { }

Estaba mirando el for..inbucle JS , pero parece que no hay forma de especificar el as. Si hago esto con un bucle for 'normal' ( for(var i = 0; i < data.length; i++), ¿hay alguna manera de obtener los pares clave => valor?

cabaret
fuente

Respuestas:

216

Si puede usar ES6 de forma nativa o con Babel (compilador js), puede hacer lo siguiente:

const test = {a: 1, b: 2, c: 3};

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

Lo que imprimirá esta salida:

a 1
b 2
c 3

El Object.entries()método devuelve una matriz de [key, value]pares de propiedades enumerables propias de un objeto dado , en el mismo orden que el proporcionado por un for...inbucle (la diferencia es que un bucle for-in también enumera propiedades en la cadena prototipo) .

¡Espero eso ayude! =)

Francesco Casula
fuente
1
Esto funciona perfecto, solo me pregunto: en comparación con "para la clave en el objeto y luego obtener valor por objeto [clave]", ¿cuál da un mejor rendimiento?
lsheng
1
En este caso específico, supongo que es más lento debido a la Object.entriesllamada. Sin embargo, no ejecuté ninguna prueba.
Francesco Casula
66
Esta es la mejor respuesta a la pregunta en cuestión, que se refería a tomar tanto la clave como el valor en el bucle for.
cipak
44
La respuesta aceptada debe actualizarse ya que esto realmente responde la pregunta, aunque no estaba disponible en el momento de la pregunta.
Marc Qualie
1
Es posible que desee verificar esta pregunta: stackoverflow.com/questions/47213651/… que parece indicar que se recomendaría una sintaxis de este tipo: Object.keys (myObject) .forEach (key => {...
Will59
519
for (var k in target){
    if (target.hasOwnProperty(k)) {
         alert("Key is " + k + ", value is " + target[k]);
    }
}

hasOwnPropertyse utiliza para verificar si targetrealmente tiene esa propiedad, en lugar de haberla heredado de su prototipo. Un poco más simple sería:

for (var k in target){
    if (typeof target[k] !== 'function') {
         alert("Key is " + k + ", value is" + target[k]);
    }
}

Es sólo comprueba que kno es un método (como si targetes arrayque obtendrá una gran cantidad de métodos de alerta, por ejemplo indexOf, push, pop, etc.)

J0HN
fuente
87
Otra forma de iterar solo sobre propiedades "propias" es Object.keys. Object.keys(target).forEach(function (key) { target[key]; });.
katspaugh
3
no va a funcionar si targetse crea usando Object.create(null), el código debe cambiarse target.hasOwnProperty(k)->Object.prototype.hasOwnProperty.call(target,k)
Azder
¿Por qué no utilizar las variables dadas en el ejemplo de la pregunta? Lo que aquí está k, targety property? Para mí, no javascripter esta área de indefinido :)
Gediminas
2
Object.keys (target) .forEach ((key) => {target [key];}); para Angular
askilondz
315

Nadie lo ha mencionado, Object.keysasí que lo mencionaré.

Object.keys(obj).forEach(function (key) {
   // do something with obj[key]
});
cabra negra
fuente
3
Nota: No es compatible con IE8 y versiones inferiores.
Edwin Stoteler
1
En este punto, debería estar utilizando una cuña ES5. Si vives en el agradable futuro de ES6, usa for of tc39wiki.calculist.org/es6/for-of
goatslacker el
17
Vale la pena señalar, que "No hay forma de detener o romper un ciclo forEach () que no sea lanzando una excepción"
rluks
Object.keys (obj) .forEach ((key) => {}); para Angular
askilondz
No funciona en ES6 o no lo entiendo. Felix tiene una respuesta mejor y más legible a continuación: data.forEach (function (value, index) {console.log (index); // 0, 1, 2 ...});
gtamborero
115

para ... en trabajará para ti.

for( var key in obj ) {
  var value = obj[key];
}

En JavaScript moderno también puedes hacer esto:

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

}
Pablo
fuente
64
var obj = {...};
for (var key in obj) {
    var value = obj[key];

}

La sintaxis php es solo azúcar.

Zirak
fuente
Esto también iterará en todas las propiedades heredadas. Para evitar esto, use .hasOwnProperty ().
LSerni
24

Supongo que sabe que esa ies la clave y que puede obtener el valor a través de data[i](y solo quiere un atajo para esto).

ECMAScript5 introdujo forEach [MDN] para las matrices (parece que tiene una matriz):

data.forEach(function(value, index) {

});

La documentación de MDN proporciona una cuña para los navegadores que no lo admiten.

Por supuesto, esto no funciona para los objetos, pero puede crear una función similar para ellos:

function forEach(object, callback) {
    for(var prop in object) {
        if(object.hasOwnProperty(prop)) {
            callback(prop, object[prop]);
        }
    }
}

Desde que etiquetaste la pregunta con , jQuery proporciona $.each [docs] que recorre las estructuras de matriz y de objeto.

Felix Kling
fuente
Eso es Array forEach, no un objeto forEach.
2
¿Entonces? Aparentemente, el OP está girando sobre una matriz.
Felix Kling
También Mozilla (Firefox, SpiderMonkey-C, Rhino & c) tiene una extensión no estándar que permite la for eachsintaxis. for each (let val in myObj) console.log(val);.
katspaugh
2
@katspaugh: Correcto, pero como es solo Mozilla, no parece ser muy útil.
Felix Kling
Muchas gracias por tu respuesta. Leeré la información que proporcionaste. Su suposición al comienzo de la respuesta era correcta, lo sabía, excepto que me dio tanta importancia con este proyecto que no puedo concentrarme y lo olvidé ... Gracias.
cabaret
10

Puedes usar el for..inpara eso.

for (var key in data)
{
    var value = data[key];
}
Christoph Winkler
fuente
9
for (var key in myMap) {
    if (myMap.hasOwnProperty(key)) {
        console.log("key =" + key);
        console.log("value =" + myMap[key]);
    }
}

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. El uso de hasOwnProperty () los filtra.

Siddhu
fuente
2

ES6 proporcionará Map.prototype.forEach (devolución de llamada) que se puede usar de esta manera

myMap.forEach(function(value, key, myMap) {
                        // Do something
                    });
Stephen Murby
fuente
2
¿Para qué sirve el parámetro myMap?
phil294
Un mapa no es un objeto. Son cosas completamente separadas.
Dakusan
2
La función forEach no contiene la 'clave' de la matriz, sino más bien el índice del elemento que está iterando actualmente.
Francis Malloch
2
let test = {a: 1, b: 2, c: 3};
Object.entries(test).forEach(([key, value]) => console.log(key, value))

// a 1
// b 2
// c 3
吴毅 凡
fuente
55
Puede agregar alguna explicación con el código que publicó en lugar de publicar un código simple que podría no ser comprensible.
AaoIi
Object.entries saca una matriz de matrices basadas en los pares clave / valor del objeto original: [['a', 1],['b',2],['c',3]]. El forEachdeconstruye cada una de las matrices de clave / valor y establece las dos variables a keyy value, para ser utilizado como desea que la función - aquí en la salida console.log.
Mark Swardstrom el
1

Puede usar un bucle 'for in' para esto:

for (var key in bar) {
     var value = bar[key];
}
Richard Dalton
fuente
1

A continuación se muestra un ejemplo que se acerca lo más posible.

for(var key in data){
  var value = data[key];    
  //your processing here
}

Si está utilizando jQuery, consulte: http://api.jquery.com/jQuery.each/

Aidamina
fuente
1

Si está usando Lodash , puede usar_.forEach

_.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
  console.log(key + ": " + value);
});
// => Logs 'a: 1' then 'b: 2' (iteration order is not guaranteed).
Gil Epshtain
fuente
1

En los últimos años desde que se hizo esta pregunta, Javascript ha agregado algunas características nuevas. Uno de ellos es el método Object.Entries .

Copiado directamente de MDN es el fragmento de código siguiente


const object1 = {
  a: 'somestring',
  b: 42
};

for (let [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}
David
fuente
-2

sí, puedes tener matrices asociativas también en javascript:

var obj = 
{
    name:'some name',
    otherProperty:'prop value',
    date: new Date()
};
for(i in obj)
{
    var propVal = obj[i]; // i is the key, and obj[i] is the value ...
}
Alex Pacurar
fuente
@PaulPRO ... todo en javascript es un par clave-valor (por lo tanto, un objeto es de hecho una matriz asociativa de pares clave-valor ...)
Alex Pacurar
@AlexPacurar y la matriz asociativa tiene un orden. Un objeto no está ordenado.
esa
@Raynos puede que tenga razón ... será de gran ayuda explicar exactamente cómo se desordena un objeto ... dado el ejemplo anterior, uno esperaría que la 'i' en el bucle for sea [name, otherProperty, y finalmente fecha] ... entonces, ¿en qué situación se mezclará el orden de las propiedades de un objeto?
Alex Pacurar
@AlexPacurar el orden particular en que se repetirá sobre el objeto es específico del navegador. Algunos lo hacen por orden alfabético, algunos lo hacen orden de definición, etc
Raynos
3
@Raynos: ¿Se ordenan necesariamente las matrices asociativas? A menudo he visto el término usado de manera más general. Por ejemplo, en el artículo de Wikipedia de matriz asociativa .
Jeremy Banks
-8
var global = (function() {
   return this;
})();

// Pair object, similar to Python

function Pair(key, value) {
    this.key = key;
    this.value = value;

    this.toString = function() {
       return "(" + key + ", " + value + ")";
    };
}

/**
 * as function
 * @param {String} dataName A String holding the name of your pairs list.
 * @return {Array:Pair} The data list filled
 *    with all pair objects.
 */
Object.prototype.as = function(dataName) {
    var value, key, data;
    global[dataName] = data = [];

    for (key in this) {
       if (this.hasOwnProperty(key)) {
          value = this[key];

          (function() {
             var k = key,
                 v = value;

            data.push(new Pair(k, v));
          })();
       }
    }

    return data;
};

var d = {
   'one': 1,
   'two': 2
};

// Loop on your (key, list) pairs in this way
for (var i = 0, max = d.as("data").length; i < max; i += 1) {
   key = data[i].key;
   value = data[i].value;

   console.log("key: " + key + ", value: " + value);
}

// delete data when u've finished with it.
delete data;
usuario278064
fuente