web-dev-qa-db-fra.com

Comment passer en boucle dans un objet JavaScript simple avec les objets en tant que membres?

Comment puis-je parcourir tous les membres d'un objet JavaScript, y compris les valeurs qui sont des objets.

Par exemple, comment pourrais-je parcourir ceci (en accédant à "your_name" et à "your_message" pour chacun)?

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar"
    }
}
1361
edt
for (var key in validation_messages) {
    // skip loop if the property is from prototype
    if (!validation_messages.hasOwnProperty(key)) continue;

    var obj = validation_messages[key];
    for (var prop in obj) {
        // skip loop if the property is from prototype
        if(!obj.hasOwnProperty(prop)) continue;

        // your code
        alert(prop + " = " + obj[prop]);
    }
}
1925
AgileJon

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

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

//
//	Visit non-inherited enumerable keys
//
Object.keys(obj).forEach(function(key) {

  console.log(key, obj[key]);

});

663
Axel Rauschmayer

Le problème avec ça

for (var key in validation_messages) {
   var obj = validation_messages[key];
   for (var prop in obj) {
      alert(prop + " = " + obj[prop]);
   }
}

est que vous allez également parcourir le prototype de l’objet primitif.

Avec celui-ci vous l'éviterez:

for (var key in validation_messages) {
   if (validation_messages.hasOwnProperty(key)) {
      var obj = validation_messages[key];
      for (var prop in obj) {
         if (obj.hasOwnProperty(prop)) {
            alert(prop + " = " + obj[prop]);
         }
      }
   }
}
374
Chango

Dans ES6, vous pouvez parcourir un objet comme celui-ci: (using arrow function )

Object.keys(myObj).forEach(key => {
    console.log(key);          // the name of the current key.
    console.log(myObj[key]);   // the value of the current key.
});

jsbin

Dans ES7, vous pouvez utiliser Object.entries au lieu de Object.keys et parcourir un objet comme celui-ci:

Object.entries(myObj).forEach(([key, val]) => {
    console.log(key);          // the name of the current key.
    console.log(val);          // the value of the current key.
});

Ce qui précède fonctionnerait aussi comme un one-liner:

Object.keys(myObj).forEach(key => console.log(key, myObj[key]));

jsbin

Si vous souhaitez également parcourir des objets imbriqués, vous pouvez utiliser une fonction recursive (ES6):

const loopNestedObj = (obj) => {
  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === 'object') loopNestedObj(obj[key]);  // recurse.
    else console.log(key, obj[key]);  // or do something with key and val.
  });
};

jsbin

Identique à la fonction ci-dessus, mais avec ES7 Object.entries au lieu de Object.keys:

const loopNestedObj = (obj) => {
  Object.entries(obj).forEach(([key, val]) => {
    if (val && typeof val === 'object') loopNestedObj(val);  // recurse.
    else console.log(key, val);  // or do something with key and val.
  });
};

Si vous êtes en programmation fonctionnelle, vous pouvez utiliser Object.keys/Object.entries pour énumérer l'objet, puis traiter les valeurs, puis utiliser reduce() pour reconvertir en un nouvel objet.

const loopNestedObj = (obj) => 
  Object.keys(obj)
    // Use .filter(), .map(), etc. if you need.
    .reduce((newObj, key) => 
      (obj[key] && typeof obj[key] === 'object') ?
        {...newObj, [key]: loopNestedObj(obj[key])} :  // recurse.
        {...newObj, [key]: obj[key]},                  // Define value.
      {});
203
Rotareti

Utilisation de Underscore.js _.each :

_.each(validation_messages, function(value, key){
    _.each(value, function(value, key){
        console.log(value);
    });
});
93
Tim Santeford

Si vous utilisez la récursivité, vous pouvez renvoyer les propriétés des objets de toutes profondeurs.

function lookdeep(object){
    var collection= [], index= 0, next, item;
    for(item in object){
        if(object.hasOwnProperty(item)){
            next= object[item];
            if(typeof next== 'object' && next!= null){
                collection[index++]= item +
                ':{ '+ lookdeep(next).join(', ')+'}';
            }
            else collection[index++]= [item+':'+String(next)];
        }
    }
    return collection;
}

//example

var O={
    a:1, b:2, c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
};
var lookdeepSample= 'O={'+ lookdeep(O).join(',\n')+'}';


/*  returned value: (String)
O={
    a:1, 
    b:2, 
    c:{
        c1:3, c2:4, c3:{
            t:true, f:false
        }
    },
    d:11
}

*/
54
kennebec

Cette réponse est un agrégat des solutions fournies dans cette poster avec quelques performance commentaires . Je pense qu'il y a 2 cas d'utilisation et le PO n'a pas indiqué s'il avait besoin d'accéder aux clés pour pouvoir les utiliser pendant le processus de boucle.

I. les touches doivent être accédées,

✔ l'approche of et Object.keys

let k;
for (k of Object.keys(obj)) {

    /*        k : key
     *   obj[k] : value
     */
}

✔ l'approche in

let k;
for (k in obj) {

    /*        k : key
     *   obj[k] : value
     */
}

_ {Utilisez celui-ci avec prudence, car il pourrait imprimer les propriétés prototypes de obj

✔ l'approche ES7

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

}

Cependant, au moment de l'édition, je ne recommanderais pas la méthode ES7, car JavaScript initialise beaucoup de variables en interne pour construire cette procédure (voir les commentaires pour les preuves). À moins que vous ne développiez pas une énorme application l’optimisation, c’est correct, mais si l’optimisation est votre priorité, vous devriez y penser.

II. nous avons juste besoin d'accéder à chaque valeur,

✔ l'approche of et Object.values

let v;
for (v of Object.values(obj)) {

}

Plus de retours sur les tests:

  • Les performances de mise en cache Object.keys ou Object.values sont négligeables

Par exemple, 

const keys = Object.keys(obj);
let i;
for (i of keys) {
  //
}
// same as
for (i of Object.keys(obj)) {
  //
}
  • Dans le cas de Object.values, l’utilisation d’une boucle for native avec des variables en cache dans Firefox semble être un peu plus rapide que l’utilisation d’une boucle for...of. Toutefois, la différence n’est pas très importante et Chrome exécute for...of plus rapidement que la boucle native for; je vous recommande donc d’utiliser for...of pour traiter de Object.values dans tous les cas (tests 4 et 6).

  • Dans Firefox, la boucle for...in est très lente. Par conséquent, lorsque vous souhaitez mettre la clé en cache pendant l'itération, il est préférable d'utiliser Object.keys. Plus Chrome exécute les deux structures à vitesse égale (1er et dernier tests). 

Vous pouvez vérifier les tests ici: https://jsperf.com/es7-and-misc-loops

32
vdegenne

Je sais qu'il est tard, mais cela m'a pris 2 minutes pour écrire cette version optimisée et améliorée de la réponse d'AgileJon:

var key, obj, prop, owns = Object.prototype.hasOwnProperty;

for (key in validation_messages ) {

    if (owns.call(validation_messages, key)) {

        obj = validation_messages[key];

        for (prop in obj ) {

            // using obj.hasOwnProperty might cause you headache if there is
            // obj.hasOwnProperty = function(){return false;}
            // but owns will always work 
            if (owns.call(obj, prop)) {
                console.log(prop, "=", obj[prop]);
            }

        }

    }

}
29
Azder
for(var k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}
27
chaos

p est la valeur

for (var key in p) {
  alert(key + ' => ' + p[key]);
}

OU 

Object.keys(p).forEach(key => { console.log(key, p[key]) })
11
Wesam
for(var key in validation_messages){
    for(var subkey in validation_messages[key]){
        //code here
        //subkey being value, key being 'yourname' / 'yourmsg'
    }
}
8
Dmitri Farkov

Dans ES7, vous pouvez faire:

for (const [key, value] of Object.entries(obj)) {
  //
}
6
Kévin Berthommier

Voici la version améliorée et récursive de la solution AgileJon ( demo ):

function loopThrough(obj){
  for(var key in obj){
    // skip loop if the property is from prototype
    if(!obj.hasOwnProperty(key)) continue;

    if(typeof obj[key] !== 'object'){
      //your code
      console.log(key+" = "+obj[key]);
    } else {
      loopThrough(obj[key]);
    }
  }
}
loopThrough(validation_messages);

Cette solution fonctionne pour toutes sortes de profondeurs différentes.

5
JepZ

Une autre option:

var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
    console.log(x);
}
4
dude

ECMAScript-2017, qui vient d'être finalisé il y a un mois, introduit Object.values ​​(). Alors maintenant, vous pouvez faire ceci:

let v;
for (v of Object.values(validation_messages))
   console.log(v.your_name);   // jimmy billy
3
Chong Lip Phang

Je pense que cela vaut la peine de souligner que jQuery résout le problème avec $.each().

Voir: https://api.jquery.com/each/

Par exemple:

$('.foo').each(function() {
    console.log($(this));
});

$(this) étant l'unique élément à l'intérieur de l'objet. Remplacez $('.foo') par une variable si vous ne souhaitez pas utiliser le moteur de sélecteur de jQuery.

3
Daniel Dewhurst

Je ne pouvais pas obtenir les messages ci-dessus pour faire tout ce que j'étais après.

Après avoir joué avec les autres réponses ici, j'ai fait ceci. C'est hacky, mais ça marche!

Pour cet objet:

var myObj = {
    pageURL    : "BLAH",
    emailBox   : {model:"emailAddress", selector:"#emailAddress"},
    passwordBox: {model:"password"    , selector:"#password"}
};

... ce code:

// Get every value in the object into a separate array item ...
function buildArray(p_MainObj, p_Name) {
    var variableList = [];
    var thisVar = "";
    var thisYes = false;
    for (var key in p_MainObj) {
       thisVar = p_Name + "." + key;
       thisYes = false;
       if (p_MainObj.hasOwnProperty(key)) {
          var obj = p_MainObj[key];
          for (var prop in obj) {
            var myregex = /^[0-9]*$/;
            if (myregex.exec(prop) != prop) {
                thisYes = true;
                variableList.Push({item:thisVar + "." + prop,value:obj[prop]});
            }
          }
          if ( ! thisYes )
            variableList.Push({item:thisVar,value:obj});
       }
    }
    return variableList;
}

// Get the object items into a simple array ...
var objectItems = buildArray(myObj, "myObj");

// Now use them / test them etc... as you need to!
for (var x=0; x < objectItems.length; ++x) {
    console.log(objectItems[x].item + " = " + objectItems[x].value);
}

... produit ceci dans la console:

myObj.pageURL = BLAH
myObj.emailBox.model = emailAddress
myObj.emailBox.selector = #emailAddress
myObj.passwordBox.model = password
myObj.passwordBox.selector = #password
2
user1833875

var obj={
name:"SanD",
age:"27"
}
Object.keys(obj).forEach((key)=>console.log(key,obj[key]));

Pour parcourir en boucle un objet JavaScript, nous pouvons utiliser forEach et pour optimiser le code, nous pouvons utiliser la fonction flèche 

1
Sandip Bailkar

La solution qui fonctionne pour moi est la suivante

_private.convertParams=function(params){
    var params= [];
    Object.keys(values).forEach(function(key) {
        params.Push({"id":key,"option":"Igual","value":params[key].id})
    });
    return params;
}
0
Jorge Santos Neill

Peu de façons de faire ça ... 

1) 2 couches pour ... en boucle ...

for (let key in validation_messages) {
   const vmKeys = validation_messages[key];
   for (let vmKey in vmKeys) {
      console.log(vmKey + vmKeys[vmKey]);
   }
}

2) Utilisation de Object.key

Object.keys(validation_messages).forEach(key => {
   const vmKeys = validation_messages[key];
   Object.keys(vmKeys).forEach(key => {
    console.log(vmKeys + vmKeys[key]);
   });
});

3) Fonction récursive

const recursiveObj = obj => {
  for(let key in obj){
    if(!obj.hasOwnProperty(key)) continue;

    if(typeof obj[key] !== 'object'){
      console.log(key + obj[key]);
    } else {
      recursiveObj(obj[key]);
    }
  }
}

Et appelez ça comme:

recursiveObj(validation_messages);
0
Alireza