Comment parcourir ou énumérer un objet JavaScript?

2882

J'ai un objet JavaScript comme le suivant:

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

Maintenant , je veux faire une boucle à travers tous les péléments ( p1, p2, p3...) et obtenir les clés et les valeurs. Comment puis je faire ça?

Je peux modifier l'objet JavaScript si nécessaire. Mon objectif ultime est de parcourir certaines paires de valeurs clés et, si possible, je veux éviter de les utiliser eval.

Tanmoy
la source
9
J'ai changé JSON en JavaScript (objet) pour éviter de confondre les littéraux d'objet et JSON.
Felix Kling

Réponses:

4371

Vous pouvez utiliser la for-inboucle comme indiqué par d'autres. Cependant, vous devez également vous assurer que la clé que vous obtenez est une propriété réelle d'un objet et qu'elle ne provient pas du prototype.

Voici l'extrait:

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

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

For-of avec une alternative Object.keys ():

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

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

Remarquez l'utilisation de for-ofau lieu de for-in, s'il n'est pas utilisé, il renverra undefined sur les propriétés nommées et Object.keys()garantit l'utilisation des seules propriétés de l'objet sans les propriétés de la chaîne de prototype entières

En utilisant la nouvelle Object.entries()méthode:

Remarque: Cette méthode n'est pas prise en charge nativement par Internet Explorer. Vous pouvez envisager d'utiliser un Polyfill pour les anciens navigateurs.

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

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}
levik
la source
34
Je proposerais que vous changiez la ligne d'alerte pour plus de clarté enalert(key + " -> " + JSON.stringify(p[key]));
Steve Midgley
80
Pouvez-vous expliquer la nécessité de hasOwnProperty? Qu'entendez-vous par prototype?
kamaci
331
En javascript, chaque objet a un tas de paires clé-valeur intégrées qui ont des méta-informations. Lorsque vous parcourez toutes les paires clé-valeur pour un objet, vous les parcourez également. hasOwnPropery () les filtre.
danieltalsky
57
En fait, For ... in n'est pas obsolète. Pour chaque ... en est. Mais j'aime beaucoup le terme archéologues ... Je vais devoir commencer à l'utiliser.
Ben Y
17
chaque objet en javascript (en fait une paire clé-valeur) a une propriété appelée __proto__ou prototype. Cette propriété a une référence à son objet parent. Un objet hérite automatiquement de la propriété de son parent. C'est la raison de l'utilisation hasOwnProperty, ce qui signifie que nous nous intéressons aux propriétés des objets et non à leurs propriétés parentales.
Zubair Alam
1104

Sous ECMAScript 5, vous pouvez combiner Object.keys()et Array.prototype.forEach():

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

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

ECMAScript 6 ajoute for...of:

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

ECMAScript 8 ajoute Object.entries()ce qui évite d'avoir à rechercher chaque valeur dans l'objet d'origine:

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

Vous pouvez combiner for...of, déstructurer et Object.entries:

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

Les deux Object.keys()et Object.entries()itèrent les propriétés dans le même ordre qu'une for...inboucle, mais ignorent la chaîne prototype . Seules les propriétés énumérables de l'objet sont itérées.

Axel Rauschmayer
la source
21
Pourquoi la norme ne prévoyait-elle pas Object.forEach(obj, function (value, key) {...})? :( Ce obj.forEach(function...)serait certainement plus court et complémentaire Array.prototype.forEach, mais cela risquerait de faire en sorte que les objets définissent leur propre forEachpropriété. Je suppose qu'il Object.keysprotège contre le rappel modifiant les clés de l'objet.
David Harkness
7
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness
7
@DavidHarkness Il y a des entrées Object dans ES2017. Là, vous pouvez faire ce qui suit: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([clé, valeur] est la déstructuration du tableau, pour accéder directement aux deux éléments. Et vous devez encapsuler les paramètres dans des parenthèses supplémentaires.)
Andreas Linnert
comment obtenir indexla clé dans json? Ou si nécessaire, dois-je utiliser un compteur séparé?
Saravanabalagi Ramachandran
3
for...ofest la norme ES6, pas ES2016.
Rax Weber
342

Vous devez utiliser la boucle for-in

Mais soyez très prudent lorsque vous utilisez ce type de boucle, car cela bouclera toutes les propriétés le long de la chaîne du prototype .

Par conséquent, lorsque vous utilisez des boucles for-in, utilisez toujours la hasOwnPropertyméthode pour déterminer si la propriété actuelle dans l'itération est vraiment une propriété de l'objet que vous vérifiez:

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
la source
31
C'est mieux que la solution de levik car elle permet à la logique principale d'être une seule boucle imbriquée au lieu de deux; ce qui facilite la lecture du code. Même si je perdais les crochets autour de la suite; ils sont superflus.
SystemicPlural
52
Je ne retirerais pas le { }personnellement parce qu'un ifsans eux rend peu clair ce qui fait partie de ifce qui ne l'est pas. Mais je suppose que ce n'est qu'une question d'opinion :)
pimvdb
34
Oui, je préfère garder le { }principalement pour éviter toute confusion si l'on a besoin plus tard d'ajouter quelque chose à la ifportée.
Andreas Grech
8
En lisant mon commentaire précédent, je me suis rendu compte que je n'avais pas utilisé les termes corrects, car j'ai dit "si portée"; mais gardez à l'esprit que JavaScript n'a qu'une portée de fonction. Donc, ce que je voulais dire, c'était "si bloquer".
Andreas Grech
1
eomeroff, si vous êtes vraiment inquiet à ce sujet, vous pouvez toujours faire quelque chose comme: Object.prototype.hasOwnProperty.call(p, prop) Cependant, cela ne peut pas non plus protéger contre les manipulations de Object.prototype ...
jordancpaul
252

La question ne sera pas complète si nous ne mentionnons pas de méthodes alternatives pour parcourir les objets.

De nos jours, de nombreuses bibliothèques JavaScript bien connues fournissent leurs propres méthodes d'itération sur des collections, c'est-à-dire sur des tableaux , des objets et des objets de type tableau . Ces méthodes sont pratiques à utiliser et sont entièrement compatibles avec n'importe quel navigateur.

  1. Si vous travaillez avec jQuery , vous pouvez utiliser la jQuery.each()méthode. Il peut être utilisé pour itérer de manière transparente sur les objets et les tableaux:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. Dans Underscore.js, vous pouvez trouver une méthode _.each(), qui itère sur une liste d'éléments, donnant chacun à son tour à une fonction fournie (faites attention à l'ordre des arguments dans la fonction iteratee !):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  3. Lo-Dash propose plusieurs méthodes pour itérer sur les propriétés des objets. Basic _.forEach()(ou son alias _.each()) est utile pour parcourir à la fois les objets et les tableaux, mais (!) Les objets avec lengthpropriété sont traités comme des tableaux, et pour éviter ce comportement, il est suggéré d'utiliser les méthodes _.forIn()et _.forOwn()(elles ont également l' valueargument en premier):

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

    _.forIn()itère sur les propriétés énumérables propres et héritées d'un objet, tandis qu'il _.forOwn()itère uniquement sur les propriétés propres d'un objet (essentiellement en hasOwnPropertyfonction de la fonction). Pour les objets simples et les littéraux d'objets, n'importe laquelle de ces méthodes fonctionnera correctement.

Généralement, toutes les méthodes décrites ont le même comportement avec tous les objets fournis. En plus d'utiliser une for..inboucle native sera généralement plus rapide que n'importe quelle abstraction, par exemple jQuery.each(), ces méthodes sont considérablement plus faciles à utiliser, nécessitent moins de codage et offrent une meilleure gestion des erreurs.

Vision
la source
4
Pour obtenir la valeur: $ .each (obj, fonction (clé, valeur) {console.log (value.title);});
Ravi Ram
2
C'est marrant de voir comment le soulignement et jquery ont changé les paramètres :)
ppasler
52

Dans ECMAScript 5, vous avez une nouvelle approche dans les domaines d'itération du littéral - Object.keys

Plus d'informations que vous pouvez voir sur MDN

Mon choix est ci-dessous comme une solution plus rapide dans les versions actuelles des navigateurs (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;
}

Vous pouvez comparer les performances de cette approche avec différentes implémentations sur jsperf.com :

Prise en charge du navigateur que vous pouvez voir sur la table compat de Kangax

Pour les anciens navigateurs, vous disposez d' un polyfill simple et complet

UPD:

comparaison des performances pour tous les cas les plus populaires dans cette question sur perfjs.info:

itération littérale d'objet

Pencroff
la source
En effet, je voulais juste poster cette méthode. Mais tu m'as battu :(
Jamie Hutber
50

Préface:

  • Les propriétés des objets peuvent être propres (la propriété se trouve sur l'objet lui-même) ou héritées (pas sur l'objet lui-même, sur l'un de ses prototypes).
  • Les propriétés des objets peuvent être énumérables ou non énumérables . Les propriétés non énumérables sont exclues de nombreux énumérations / tableaux de propriétés.
  • Les noms de propriété peuvent être des chaînes ou des symboles. Les propriétés dont les noms sont des symboles sont exclues de nombreux énumérations / tableaux de propriétés.

Ici, en 2018, vos options pour parcourir les propriétés d'un objet sont (certains exemples suivent la liste):

  1. for-in[ MDN , spec ] - Une structure de boucle qui parcourt les noms des propriétés énumérables d'un objet , y compris celles héritées, dont les noms sont des chaînes
  2. Object.keys[ MDN , spec ] - Une fonction fournissant un tableau des noms de d'un objet propre , dénombrables propriétés dont les noms sont des chaînes.
  3. Object.values[ MDN , spec ] - Une fonction fournissant un tableau des valeurs de l' objet d'un propre , dénombrables propriétés.
  4. Object.entries[ MDN , spec ] - Une fonction fournissant un tableau des noms et des valeurs de d'un objet propre , dénombrables propriétés (chaque entrée de la matrice est une [name, value]matrice).
  5. Object.getOwnPropertyNames[ MDN , spec ] - Une fonction fournissant un tableau des noms d'un objet de propres propriétés (même les non-dénombrables) dont les noms sont des chaînes.
  6. Object.getOwnPropertySymbols[ MDN , spec ] - Une fonction fournissant un tableau des noms d'un objet de propres propriétés (même les non-dénombrables) dont les noms sont des symboles.
  7. Reflect.ownKeys[ MDN , spec ] - Une fonction fournissant un tableau des noms d'un objet de propres propriétés (même les non-dénombrables), que ces noms sont des chaînes ou des symboles.
  8. Si vous voulez toutes les propriétés d'un objet, y compris celles héritées non dénombrables, vous devez utiliser une boucle et Object.getPrototypeOf[ MDN , spécifications ] et l' utilisation Object.getOwnPropertyNames, Object.getOwnPropertySymbolsou Reflect.ownKeyssur chaque objet dans la chaîne de prototype ( par exemple au bas de cette réponse).

Avec tous sauf for-in, vous utiliseriez une sorte de boucle construction sur le tableau ( for, for-of, forEach, etc.).

Exemples:

for-in:

Object.keys (avec une for-ofboucle, mais vous pouvez utiliser n'importe quelle construction en boucle) :

Object.values:

Object.entries:

Object.getOwnPropertyNames:

Object.getOwnPropertySymbols:

Reflect.ownKeys:

Toutes les propriétés , y compris les propriétés non énumérables héritées:

TJ Crowder
la source
Belle addition de propriétés d'objet énumérables / non énumérables.
serraosays
49

Vous pouvez simplement itérer dessus comme:

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

Notez que keycela ne prendra pas la valeur de la propriété, c'est juste une valeur d'index.

Bryan
la source
13
Ceci est répété et n'est même pas entièrement correct. Vous devez avoir une vérification de hasOwnProperty pour que cela fonctionne correctement
Vatsal
4
J'ai d'abord rétrogradé cela sur la base du commentaire ci-dessus jusqu'à ce que je réalise que cette réponse est venue en premier, elle n'est donc pas "répétée". Il est peut-être incomplet mais fonctionne très bien dans de nombreux cas.
billynoah
27

Depuis que es2015 devient de plus en plus populaire, je publie cette réponse qui inclut l'utilisation du générateur et de l'itérateur pour itérer en douceur par [key, value]paires. Comme c'est possible dans d'autres langues, par exemple Ruby.

Ok voici un code:

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

Toutes les informations sur la façon dont vous pouvez faire un itérateur et un générateur que vous pouvez trouver sur la page Mozilla du développeur.

J'espère que cela a aidé quelqu'un.

ÉDITER:

ES2017 inclura Object.entriesce qui rendra l'itération sur des [key, value]paires d'objets encore plus facile. On sait maintenant qu'il fera partie d'une norme selon les informations d'étape ts39 .

Je pense qu'il est temps de mettre à jour ma réponse pour la laisser devenir encore plus fraîche qu'elle ne l'est maintenant.

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

Vous pouvez trouver plus d'informations sur l'utilisation sur la page MDN

FieryCod
la source
Cela me semble totalement superflu / inutile. Souhaitez-vous l'ajouter à chaque objet de votre système? Je pensais que le but de fournir un itérateur était pour que vous puissiez faire «pour (const [k, v] de myObject)». Cela ressemble à du code supplémentaire fournissant peu de valeur supplémentaire.
Dean Radcliffe
22
for(key in p) {
  alert( p[key] );
}

Remarque: vous pouvez le faire sur des tableaux, mais vous parcourrez également les lengthpropriétés et d'autres.

Richard Levasseur
la source
4
Lorsque vous utilisez une boucle for comme celle-ci, elle keyprendra simplement une valeur d'index, ce qui alertera simplement 0, 1, 2, etc.
Bryan
1
Il s'agit de la méthode d'itération de tableau la plus lente en JavaScript. Vous pouvez vérifier cela sur votre ordinateur - La meilleure façon d'itérer sur les tableaux en JavaScript
Pencroff
5
@Pencroff: le problème est que la question n'est pas de boucler à travers les tableaux ...;)
Sk8erPeter
C'est quelque chose que je ne comprends pas sur stackoverflow. Richard a donné la bonne réponse, et il a été le premier à donner cette réponse, mais il n'a obtenu aucun +1? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }fait apparaître "p1" et "p2" dans les alertes, alors qu'est-ce qui ne va pas ???
Sebastian
5
Je pense que la principale différence est la qualité: les autres réponses indiquent non seulement comment, mais aussi les mises en garde (par exemple, le prototype) et comment y faire face. À mon humble avis, ces autres réponses sont meilleures que les miennes :).
Richard Levasseur
20

Après avoir parcouru toutes les réponses ici, hasOwnProperty n'est pas requis pour mon propre usage car mon objet json est propre; il n'y a vraiment aucun sens à ajouter un traitement javascript supplémentaire. C'est tout ce que j'utilise:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}
Francis Lewis
la source
18
Que l'objet JSON soit propre ou non n'a pas d'importance. Si à tout autre moment un code définit une propriété Object.prototype, elle sera énumérée par for..in. Si vous êtes sûr de ne pas utiliser de bibliothèques pour cela, vous n'avez pas besoin d'appeler hasOwnProperty.
G-Wiz
4
Il peut être complètement propre s'il est créé avecObject.create(null)
Juan Mendes
20

via prototype avec forEach () qui devrait ignorer les propriétés de la chaîne de prototype :

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
la source
2
Soyez prudent avec le prototype: obj = { print: 1, each: 2, word: 3 }produit TypeError: number is not a function. Utiliser forEachpour faire correspondre la Arrayfonction similaire peut réduire quelque peu le risque.
David Harkness
18

Il est intéressant que les personnes dans ces réponses aient abordé les deux Object.keys()et for...ofne les aient jamais combinées:

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

Vous ne pouvez pas juste for...ofun Objectparce que ce n'est pas un itérateur, et for...indexou .forEach()ing Object.keys()est laid / inefficace.
Je suis content que la plupart des gens s'abstiennent for...in(avec ou sans vérification .hasOwnProperty()) car c'est aussi un peu compliqué, donc à part ma réponse ci-dessus, je suis ici pour dire ...


Vous pouvez faire itérer les associations d'objets ordinaires! Se Mapcomporter comme des s avec une utilisation directe du for...of
DEMO sophistiqué fonctionnant dans Chrome et FF (je suppose que ES6 uniquement)

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

Tant que vous incluez ma cale ci-dessous:

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

Sans avoir à créer un véritable objet Map qui n'a pas le bon sucre syntaxique.

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

En fait, avec ce shim, si vous vouliez toujours profiter des autres fonctionnalités de Map (sans les caler toutes), mais vouliez toujours utiliser la notation d'objet soignée, puisque les objets sont maintenant itérables, vous pouvez maintenant simplement en faire une Map!

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

Pour ceux qui n'aiment pas faire de shim, ou jouer avec prototypeen général, n'hésitez pas à faire la fonction sur la fenêtre à la place, en l'appelant quelque chose comme ça 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;
}

Maintenant, vous pouvez simplement l'appeler comme une fonction ordinaire, rien d'autre n'est affecté

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

ou

for (let pair of getObjIterator(ordinaryObject))

Il n'y a aucune raison pour que cela ne fonctionne pas.

Bienvenue dans le futur.

Hashbrown
la source
1
Affaire au point . Tant que les gens défilent vers le bas et trouvent cela utile, c'est tout ce qui compte. Habituellement, c'est moi qui essaie de faire quelque chose, qui n'aime pas ce que je vois en ligne, je finis par le comprendre, puis je reviens pour partager. C'est bon doco, j'ai trouvé mes propres réponses avant de googler des choses que j'avais complètement oubliées!
Hashbrown
@HelpMeStackOverflowMyOnlyHope Personnellement, je n'aime pas modifier les prototypes d'objets que je n'ai pas définis moi-même.
Janus Troelsen
@JanusTroelsen avez-vous même lu toute la réponse? 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
Notez que cette technique ne fonctionne pas sur les objets simples, mais néanmoins utile.
noɥʇʎԀʎzɐɹƆ
cela fonctionne pour les objets simples, c'est littéralement le point entier (ainsi que les noms de variables comme ordinaryObjectpour souligner que la magie fonctionne toujours pour ces types). Avez-vous vérifié les démos; qu'est-ce qui ne fonctionne pas pour vous, @ noɥʇʎԀʎzɐɹƆ? (PS, votre image de profil SE est le patron)
Hashbrown
13

Object.keys (obj): tableau

récupère toutes les clés de chaîne de toutes les propriétés propres (non héritées) énumérables.

Il donne donc la même liste de clés que vous souhaitez en testant chaque clé d'objet avec hasOwnProperty. Vous n'avez pas besoin de cette opération de test supplémentaire et Object.keys( obj ).forEach(function( key ){})vous êtes censé être plus rapide. Prouvons-le:

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.");

Dans mon Firefox, j'ai les résultats suivants

  • L'approche Object.keys a pris 40,21101451665163 millisecondes.
  • for ... in / hasOwnProperty a pris 98,26163508463651 millisecondes.

PS. sur Chrome, la différence est encore plus grande http://codepen.io/dsheiko/pen/JdrqXa

PS2: Dans ES6 (EcmaScript 2015), vous pouvez parcourir plus facilement un objet itérable:

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
la source
si vous n'avez pas envie de laisser tomber la notation {}, vous pouvez toujours l'utiliser of sans créer de Maps
Hashbrown
13

Voici une autre méthode pour parcourir un objet.

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


Object.keys(p).forEach(key => { console.log(key, p[key]) })

Patel dur
la source
3
C'est assez cool, mais pour les gros objets, la forméthode peut être plus performante.
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
la source
12

Vous pouvez également utiliser Object.keys () et parcourir les clés d'objet comme ci-dessous pour obtenir la valeur:

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

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});

Onera
la source
Vous m'avez fait gagner du temps, merci
Swap-IOS-Android
Heureux de savoir :)
Onera
8

Uniquement du code JavaScript sans dépendances:

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
la source
8

La Object.keys()méthode renvoie un tableau des propres propriétés énumérables d'un objet donné. En savoir plus ici

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

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

George Bailey
la source
8

Performance

Aujourd'hui 2020.03.06 j'effectue des tests des solutions choisies sur Chrome v80.0, Safari v13.0.5 et Firefox 73.0.1 sur MacOs High Sierra v10.13.6

Conclusions

  • solutions basées sur for-in (A, B) sont rapides (ou les plus rapides) pour tous les navigateurs pour petits et grands objets
  • étonnamment for-of (H), la solution est rapide sur le chrome pour les petits et les gros objets
  • solutions basées sur un index explicite i (J, K) sont assez rapides sur tous les navigateurs pour les petits objets (pour firefox aussi rapide pour les gros objets mais moyenne rapide sur les autres navigateurs)
  • les solutions basées sur des itérateurs (D, E) sont les plus lentes et non recommandées
  • la solution C est lente pour les gros objets et moyenne-lente pour les petits objets

entrez la description de l'image ici

Détails

Des tests de performance ont été effectués pour

  • petit objet - avec 3 champs - vous pouvez effectuer le test sur votre machine ICI
  • 'grand' objet - avec 1000 champs - vous pouvez effectuer des tests sur votre machine ICI

Les extraits ci-dessous présentent les solutions utilisées

Et voici le résultat pour les petits objets sur chrome

entrez la description de l'image ici

Kamil Kiełczewski
la source
7

Vous pouvez ajouter une fonction forEach simple à tous les objets, vous pouvez donc parcourir automatiquement n'importe quel objet:

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

Pour ceux qui n'aiment pas la méthode " for ... in ":

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

Maintenant, vous pouvez appeler simplement:

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

Si vous ne voulez pas avoir de conflits avec d'autres méthodes forEach, vous pouvez le nommer avec votre nom unique.

Biber
la source
3
La modification des prototypes d'objets intégrés (comme Object) est généralement considérée comme un anti motif car elle peut facilement provoquer des conflits avec d'autres codes. Donc, je ne recommande pas de le faire de cette façon.
Moritz
6

Les boucles peuvent être assez intéressantes lors de l'utilisation de JavaScript pur. Il semble que seul ECMA6 (nouvelle spécification JavaScript 2015) ait maîtrisé les boucles. Malheureusement, au moment où j'écris ceci, les navigateurs et l'environnement de développement intégré (IDE) populaire ont encore du mal à prendre en charge complètement les nouvelles cloches et sifflets.

En bref, voici à quoi ressemble une boucle d'objet JavaScript avant 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;
  }
}

De plus, je sais que cela est hors de portée avec cette question, mais en 2011, ECMAScript 5.1 a ajouté la forEachméthode pour les tableaux uniquement, ce qui a essentiellement créé une nouvelle façon améliorée de parcourir les tableaux tout en laissant des objets non itérables avec l'ancienne forboucle verbeuse et déroutante . Mais la partie étrange est que cette nouvelle forEachméthode ne prend pas en charge breakce qui a conduit à toutes sortes d'autres problèmes.

Fondamentalement, en 2011, il n'y a pas de véritable moyen solide de boucler en JavaScript autre que ce que de nombreuses bibliothèques populaires (jQuery, Underscore, etc.) ont décidé de réimplémenter.

Depuis 2015, nous avons maintenant une meilleure façon de boucler (et de casser) tout type d'objet (y compris les tableaux et les chaînes). Voici à quoi ressemblera finalement une boucle en JavaScript lorsque la recommandation deviendra grand public:

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

Notez que la plupart des navigateurs ne prendront pas en charge le code ci-dessus à partir du 18 juin 2016. Même dans Chrome, vous devez activer cet indicateur spécial pour qu'il fonctionne: chrome://flags/#enable-javascript-harmony

Jusqu'à ce que cela devienne la nouvelle norme, l'ancienne méthode peut toujours être utilisée, mais il existe également des alternatives dans les bibliothèques populaires ou même des alternatives légères pour ceux qui n'utilisent aucune de ces bibliothèques.

Nicolas Bouvrette
la source
Pourriez-vous fournir un violon de ce travail? Voici ma tentative. jsfiddle.net/abalter/sceeb211
abalter
@abalter Désolé, j'ai réalisé que j'avais une faute de frappe dans mon code. Je l'ai corrigé et mis à jour votre JsFiddle ici: jsfiddle.net/sceeb211/2
Nicolas Bouvrette
Je suis en chrome et j'obtiens Uncaught TypeError: Object.entries is not a function. N'est-il pas encore implémenté dans Chrome?
abalter
@abalter C'est le cas. Assurez-vous que vous avez la version 51 de Chrome et que vous avez activé le drapeau comme expliqué dans mes commentaires de modification et Jsfiddle. Vous pouvez vérifier les détails ici: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nicolas Bouvrette
Désolé d'avoir raté ça à propos du drapeau. Je vois que ce n'est pas encore une fonctionnalité entièrement implémentée.
abalter
5

Dans ES6, nous avons des symboles bien connus pour exposer certaines méthodes précédemment internes, vous pouvez l'utiliser pour définir le fonctionnement des itérateurs pour cet objet:

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

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

cela donnera le même résultat que l'utilisation de for ... dans la boucle es6.

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

Mais il est important de connaître les capacités que vous avez maintenant en utilisant es6!

Bamieh
la source
1
Un itérateur d'objet personnalisé appelle l'itérateur de tableau intégré d'un tableau généré par Object.keys()et alloué en mémoire ... Cool!
ooo
5

Je ferais cela plutôt que de vérifier obj.hasOwnerPropertydans chaque for ... inboucle.

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");
}
Lewis
la source
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
la source
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

Utiliser un for-ofsurObject.keys()

Comme:

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

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

Si vous souhaitez également parcourir les propriétés non énumérables , vous pouvez utiliser Object.getOwnPropertyNames(obj)pour renvoyer un tableau de toutes les propriétés (énumérables ou non) trouvées directement sur un objet donné.

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
la source
2
C'est fantastique, merci d'avoir posté cette réponse. Je devais introspecter un Errorobjet et je ne pouvais pas accéder aux propriétés dans une boucle ou un _.forIn(err)appel. L'utilisation Object.getOwnPropertyNames(err)m'a permis d'accéder à toutes les parties du Errorque je ne pouvais pas obtenir auparavant. Merci!
Pierce
4

Si quelqu'un doit parcourir les objets arrayObjects avec condition :

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.
la source
4

Compte tenu de ES6, je voudrais ajouter ma propre cuillère de sucre et fournir une autre approche pour itérer sur les propriétés de l'objet.

Étant donné qu'un objet JS simple n'est pas itérable juste à la sortie de la boîte, nous ne pouvons pas utiliser la for..ofboucle pour itérer sur son contenu. Mais personne ne peut nous empêcher de le rendre itérable .

Ayons un bookobjet.

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

Puisque nous l'avons fait, nous pouvons l'utiliser de cette façon:

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

Ou si vous connaissez la puissance des générateurs ES6 , vous pouvez certainement raccourcir le code ci-dessus.

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

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

}

Bien sûr, vous pouvez appliquer un tel comportement pour tous les objets en le rendant Objectitérable au prototypeniveau.

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

De plus, les objets conformes au protocole itérable peuvent être utilisés avec le nouvel opérateur d' étalement des fonctionnalités ES2015 , ce qui nous permet de lire les valeurs des propriétés des objets sous forme de tableau.

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

Ou vous pouvez utiliser l' affectation de déstructuration :

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

Vous pouvez consulter JSFiddle avec tout le code que j'ai fourni ci-dessus.

Artyom Pranovich
la source
J'ai trouvé que le code générera les valeurs mais sans clés. Est-il possible d'itérer les valeurs avec des clés?
Pika
Oui, vous pouvez. Renvoyez simplement "yield [key, obj [key]];" à partir de votre fonction de générateur, puis utilisez-la comme suit "for (let [key, value] of {}) {}"
Artyom Pranovich
4

depuis ES06, vous pouvez obtenir les valeurs d'un objet sous forme de tableau avec

let arrValues = Object.values( yourObject) ;

il retourne un tableau des valeurs des objets et il n'extrait pas les valeurs du prototype !!

MDN DOCS Object.values ​​()

et pour les clés (déjà répondu devant moi ici)

let arrKeys   = Object.keys(yourObject);
yehonatan yehezkel
la source
Les réponses demandent une solution qui renvoie à la fois les clés et les valeurs.
Sean Lindo
4

Dans le dernier script ES, vous pouvez faire quelque chose comme ceci:

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

Ankit
la source