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?


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

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.


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


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"

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

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


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)

})

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.


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


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>


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


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

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

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 .


0
const o = {
  name: "Max",
  location: "London"
};

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

Essayez en ligne

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.