Comment parcourir un objet JavaScript?

422

J'ai un objet en JavaScript:

{
    abc: '...',
    bca: '...',
    zzz: '...',
    xxx: '...',
    ccc: '...',
    // ...
}

Je veux utiliser un for boucle pour obtenir ses propriétés. Et je veux l'itérer en plusieurs parties (pas toutes les propriétés des objets à la fois).

Avec un tableau simple, je peux le faire avec une forboucle standard :

for (i = 0; i < 100; i++) { ... } // first part
for (i = 100; i < 300; i++) { ... } // second
for (i = 300; i < arr.length; i++) { ... } // last

Mais comment faire avec des objets?

nkuhta
la source
22
Gardez à l'esprit que les propriétés des objets ne sont pas stockées dans l'ordre. Lorsque vous parcourez un objet, il n'y a aucune garantie quant à l'ordre dans lequel ils apparaîtront.
James Allardice

Réponses:

852

Pour la plupart des objets, utilisez for .. in:

for (let key in yourobject) {
  console.log(key, yourobject[key]);
}

Avec ES6, si vous avez besoin de clés et de valeurs simultanément, faites

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

Pour éviter la journalisation des propriétés héritées, vérifiez avec hasOwnProperty :

for (let key in yourobject) {
   if (yourobject.hasOwnProperty(key)) {
      console.log(key, yourobject[key]);
   }
}

Vous n'avez pas besoin de vérifier hasOwnPropertylors de l'itération sur les touches si vous utilisez un objet simple (par exemple celui que vous avez créé vous-même {}).

Cette documentation MDN explique plus généralement comment traiter les objets et leurs propriétés.

Si vous voulez le faire "en morceaux", le mieux est d'extraire les clés dans un tableau. Comme la commande n'est pas garantie, c'est la bonne façon. Dans les navigateurs modernes, vous pouvez utiliser

let keys = Object.keys(yourobject);

Pour être plus compatible, vous feriez mieux de faire ceci:

 let keys = [];
 for (let key in yourobject) {      
     if (yourobject.hasOwnProperty(key)) keys.push(key);
 }

Ensuite, vous pouvez parcourir vos propriétés par index yourobject[keys[i]]::

for (let i=300; i < keys.length && i < 600; i++) { 
   console.log(keys[i], yourobject[keys[i]]);
}
Denys Séguret
la source
3
OP veut effectuer cela en morceaux, pas toutes les clés dans une seule boucle.
pawel
Oui. Objet pas complet dans une boucle.
nkuhta
2
@Cerbrus L'OP sait déjà comment itérer un tableau en plusieurs parties. L'utilisation à keyspartir du code donné devrait suffire.
Yoshi
2
@Cerbrus Veuillez lire avant de commenter! Qu'est-ce qui n'est pas clair dans "Pour être plus compatible, vous feriez mieux de faire cela" ?
Denys Séguret
2
@ am05mhz Comme je l'ai dit, c'est inutile avec la plupart des objets. Mais pas pour tous. Essayez ceci: jsbin.com/hirivubuta/1/edit?js,console,output
Denys Séguret
61

Voici une autre solution d'itération pour les navigateurs modernes:

Object.keys(obj)
  .filter((k, i) => i >= 100 && i < 300)
  .forEach(k => console.log(obj[k]));

Ou sans la fonction de filtre:

Object.keys(obj).forEach((k, i) => {
    if (i >= 100 && i < 300) {
        console.log(obj[k]);
    }
});

Cependant, vous devez considérer que les propriétés de l'objet JavaScript ne sont pas triées, c'est-à-dire n'ont pas d'ordre.

Vision
la source
Si je romps la boucle, cela recommencera au début de l'objet la prochaine fois, ce n'est pas la bonne façon.
nkuhta
21

L' utilisation que Object.entriesvous faites quelque chose comme ça.

 // array like object with random key ordering
 const anObj = { 100: 'a', 2: 'b', 7: 'c' };
 console.log(Object.entries(anObj)); // [ ['2', 'b'],['7', 'c'],['100', 'a'] ]

La méthode Object.entries () renvoie un tableau de la propre propriété énumérable d'un objet donné [clé, valeur]

Vous pouvez donc itérer sur l'objet et avoir keyet valuepour chacun de l'objet et obtenir quelque chose comme ça.

const anObj = { 100: 'a', 2: 'b', 7: 'c' };
Object.entries(anObj).map(obj => {
   const key   = obj[0];
   const value = obj[1];

   // do whatever you want with those values.
});

ou comme ça

// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});

Pour une référence, consultez les documents MDN pour les entrées d'objet

Adeel Imran
la source
18

Avec les nouvelles fonctionnalités ES6 / ES2015, vous n'avez plus besoin d'utiliser un objet pour parcourir un hachage. Vous pouvez utiliser une carte . Les cartes Javascript gardent les clés dans l'ordre d'insertion, ce qui signifie que vous pouvez les parcourir sans avoir à vérifier le hasOwnProperty, qui a toujours été vraiment un hack.

Itérer sur une carte:

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

for (var key of myMap.keys()) {
  console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"

for (var value of myMap.values()) {
  console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"

for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

ou utilisez forEach:

myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
Paul
la source
1
forEach est le préféré
pungggi
14

Si vous voulez la clé et la valeur lors de l'itération, vous pouvez utiliser une boucle for ... of avec Object.entries .

const myObj = {a: 1, b: 2}

for (let [key, value] of Object.entries(myObj)) {
    console.log(`key=${key} value=${value}`)
}

// output: 
// key=a value=1
// key=b value=2
Derek Soike
la source
7

La seule façon fiable de le faire serait d'enregistrer vos données d'objet dans 2 tableaux, l'un des clés et l'autre pour les données:

var keys = [];
var data = [];
for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        keys.push(key);
        data.push(obj[key]); // Not necessary, but cleaner, in my opinion. See the example below.
    }
}

Vous pouvez ensuite parcourir les tableaux comme vous le feriez normalement:

for(var i = 0; i < 100; i++){
    console.log(keys[i], data[i]);
    //or
    console.log(keys[i], obj[keys[i]]); // harder to read, I think.
}
for(var i = 100; i < 300; i++){
    console.log(keys[i], data[i]);
}

Je n'utilise pas Object.keys(obj), car c'est IE 9+.

Cerbrus
la source
3

-> si nous itérons sur un objet JavaScript en utilisant et en trouvant la clé du tableau d'objets

Object.keys(Array).forEach(key => {

 console.log('key',key)

})
ashishdudhat
la source
1

Si vous vouliez itérer tout l'objet à la fois, vous pouvez utiliser la for inboucle:

for (var i in obj) {
  ...
}

Mais si vous voulez diviser l'objet en parties, vous ne le pouvez pas. Il n'y a aucune garantie que les propriétés de l'objet sont dans un ordre spécifié. Par conséquent, je peux penser à deux solutions.

La première consiste à "supprimer" les propriétés déjà lues:

var i = 0;
for (var key in obj) {
    console.log(obj[key]);
    delete obj[key];
    if ( ++i > 300) break;
}

Une autre solution à laquelle je peux penser est d'utiliser Array of Arrays au lieu de l'objet:

var obj = [['key1', 'value1'], ['key2', 'value2']];

Ensuite, la forboucle standard fonctionnera.

Michał Miszczyszyn
la source
1

J'ai finalement trouvé une fonction utilitaire pratique avec une interface unifiée pour itérer les objets, les chaînes, les tableaux, les tableaux typés, les cartes, les ensembles (tous les Iterables).

const iterate = require('@a-z/iterate-it');
const obj = { a: 1, b: 2, c: 3 };

iterate(obj, (value, key) => console.log(key, value)); 
// a 1
// b 2
// c 3

https://github.com/alrik/iterate-javascript

Alrik Zachert
la source
1

Vous pouvez essayer d'utiliser lodash - une bibliothèque d'utilitaires JavaScript moderne offrant modularité, performances et extras js pour itérer rapidement les objets: -

var  users  =   {
    'fred':     { 
        'user':   'fred',
            'age':  40 
    },
    'pebbles':  { 
        'user':   'pebbles',
         'age':  1 
    }
}; 
_.mapValues(users,  function(o)  { 
    return  o.age; 
});
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
// The `_.property` iteratee shorthand.
console.log(_.mapValues(users,  'age')); // returns age property & value 
console.log(_.mapValues(users,  'user')); // returns user property & value 
console.log(_.mapValues(users)); // returns all objects 
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-compat/3.10.2/lodash.js"></script>

Parth Raval
la source
1

Pour l'itération d'objet, nous utilisons généralement une for..inboucle. Cette structure parcourra toutes les propriétés énumérables , y compris celles héritées via l'héritage prototypique. Par exemple:

let obj = {
  prop1: '1',
  prop2: '2'
}

for(let el in obj) {
  console.log(el);
  console.log(obj[el]);
}

Cependant, for..infera une boucle sur tous les éléments énumérables et cela ne nous permettra pas de diviser l'itération en morceaux. Pour ce faire, nous pouvons utiliser la Object.keys()fonction intégrée pour récupérer toutes les clés d'un objet dans un tableau. Nous pouvons ensuite diviser l'itération en plusieurs boucles for et accéder aux propriétés à l'aide du tableau de clés. Par exemple:

let obj = {
  prop1: '1',
  prop2: '2',
  prop3: '3',
  prop4: '4',
};

const keys = Object.keys(obj);
console.log(keys);


for (let i = 0; i < 2; i++) {
  console.log(obj[keys[i]]);
}


for (let i = 2; i < 4; i++) {
  console.log(obj[keys[i]]);
}

Willem van der Veen
la source
0
var Dictionary = {
  If: {
    you: {
      can: '',
      make: ''
    },
    sense: ''
  },
  of: {
    the: {
      sentence: {
        it: '',
        worked: ''
      }
    }
  }
};

function Iterate(obj) {
  for (prop in obj) {
    if (obj.hasOwnProperty(prop) && isNaN(prop)) {
      console.log(prop + ': ' + obj[prop]);
      Iterate(obj[prop]);
    }
  }
}
Iterate(Dictionary);
HovyTech
la source
1
En fait non. Cela implique que Objects sont en ordre. Ils ne sont pas. If you can make sense of the sentence it workedne fonctionne qu'en raison des détails de mise en œuvre. Il n'est pas du tout garanti de fonctionner. Vous ne devez pas non plus TitleCase vos fonctions et variables. C'est pour classes.
Florian Wendelborn
0

Vraiment un PITA, cela ne fait pas partie du Javascript standard.

/**
 * Iterates the keys and values of an object.  Object.keys is used to extract the keys.
 * @param object The object to iterate
 * @param fn (value,key)=>{}
 */
function objectForEach(object, fn) {
    Object.keys(object).forEach(key => {
        fn(object[key],key, object)
    })
}

Remarque: J'ai basculé les paramètres de rappel sur (valeur, clé) et ajouté un troisième objet pour rendre l'API cohérente avec les autres API.

Utilisez-le comme ça

const o = {a:1, b:true};
objectForEach(o, (value, key, obj)=>{
    // do something
});
Steven Spungin
la source
1
voté juste pour votre déclaration dans la première phrase. Même s'il serait préférable que la valeur soit le premier paramètre, le deuxième paramètre d'index ou de clé et le troisième paramètre d'objet, pour le rendre plus semblable au tableau forEach (). Je recommanderais cependant de recommander lodash.
LE CONTRAT DIT QUE J'AI DROIT
J'aime l'idée de l'ordre (valeur, clé). Voilà comment une bibliothèque comme Vue le fait aussi. Parce que l'objet est le contexte, il pense cependant qu'il appartient en tant que premier paramètre. C'est assez standard pour la programmation fonctionnelle.
Steven Spungin
Je serais d'accord ici sans l'ECMA-262 définissant un tableau comme un objet ayant forEach (), map (), Reduce (), filter (), qui prennent tous des rappels recevant l'ordre [valeur, index, tableau] . Un objet dans JS peut être compris comme simplement une autre collection; puis ces méthodes deviennent unifiées dans leurs paramètres de [valeur, clé | index, contexte] (c'est ce que font lodash et underscore). À mon avis, ce protocole de "collecte unifiée" est juste plus fort. De plus, l'objet n'est pas le contexte: vous pouvez définir thisce que vous voulez pour le rappel, car le rappel a son propre contexte.
LE CONTRAT DIT
J'aurais peut-être dû utiliser le récepteur de travail à la place de cela. Quoi qu'il en soit, toujours un PITA; J'accueillerais les paramètres dans n'importe quel ordre.
Steven Spungin
Oh, je vois que nous nous sommes peut-être mal compris. Je commentais toujours les paramètres de rappel et leur ordre, pas la objectForEachfonction réelle . Désolé si c'était confus.
CONTRAT DIT QUE J'AI DROIT
0

Oui. Vous pouvez parcourir un objet en utilisant la boucle for. Voici un exemple

var myObj = {
    abc: 'ABC',
    bca: 'BCA',
    zzz: 'ZZZ',
    xxx: 'XXX',
    ccc: 'CCC',
}

var k = Object.keys (myObj);
for (var i = 0; i < k.length; i++) {
    console.log (k[i] + ": " + myObj[k[i]]);
}

REMARQUE: l'exemple mentionné ci-dessus ne fonctionnera que dans IE9 +. Voir le support du navigateur Objec.keys ici .

Omprakash Arumugam
la source
0
const o = {
  name: "Max",
  location: "London"
};

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

Essayez en ligne

Vishal
la source