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"
}
}
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]);
}
}
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]);
});
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]);
}
}
}
}
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.
});
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]));
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.
});
};
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.
{});
Utilisation de Underscore.js _.each
:
_.each(validation_messages, function(value, key){
_.each(value, function(value, key){
console.log(value);
});
});
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
}
*/
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.
✔ 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.
✔ l'approche of
et Object.values
let v;
for (v of Object.values(obj)) {
}
Object.keys
ou Object.values
sont négligeablesPar 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
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]);
}
}
}
}
for(var k in validation_messages) {
var o = validation_messages[k];
do_something_with(o.your_name);
do_something_else_with(o.your_msg);
}
p est la valeur
for (var key in p) {
alert(key + ' => ' + p[key]);
}
OU
Object.keys(p).forEach(key => { console.log(key, p[key]) })
for(var key in validation_messages){
for(var subkey in validation_messages[key]){
//code here
//subkey being value, key being 'yourname' / 'yourmsg'
}
}
Dans ES7, vous pouvez faire:
for (const [key, value] of Object.entries(obj)) {
//
}
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.
Une autre option:
var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
console.log(x);
}
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
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.
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
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
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;
}
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);