web-dev-qa-db-fra.com

Utilisation d'objets dans des boucles for

Pourquoi n'est-il pas possible d'utiliser des objets dans des boucles for? Ou est-ce un bug de navigateur? Ce code ne fonctionne pas dans Chrome 42, indiquant que non défini n'est pas une fonction:

test = { first: "one"}

for(var item of test) {
  console.log(item)
}
68
Daniel Herr

J'ai créé des objets itérables avec ce code:

Object.prototype[Symbol.iterator] = function*() {
 for(let key of Object.keys(this)) {
  yield([ key, this[key] ])
} }

Usage:

for(let [ key, value ] of {}) { }

Alternativement:

for(let [ key, value ] of Object.entries({})) { }
18
Daniel Herr

La boucle pour..de ne supporte que les objets itérables comme les tableaux, pas les objets.

Pour parcourir les valeurs d'un objet, utilisez:

for (var key in test) {
    var item = test[key];
}
60
Overv

Si vous stockez des données dans un magasin de valeurs-clés, veuillez utiliser Map qui est explicitement conçu à cet effet.

Si vous devez utiliser un objet, ES2017 (ES8) vous permet d’utiliser Object.values :

const foo = { a: 'foo', z: 'bar', m: 'baz' };
for (let value of Object.values(foo)) {
    console.log(value);
}

Si cela n'est pas encore supporté, utilisez un polyfill: Version alternative pour Object.values()

Enfin, si vous prenez en charge un environnement plus ancien qui ne prend pas en charge cette syntaxe, vous devrez recourir à forEach et Object.keys:

var obj = { a: 'foo', z: 'bar', m: 'baz' };
Object.keys(obj).forEach(function (prop) {
    var value = obj[prop];
    console.log(value);
});
31
Qantas 94 Heavy

Vous pouvez utiliser cette syntaxe:

let myObject = {first: "one"};

for(let [key, value] of Object.entries(myObject)) {
    console.log(key, value); // "first", "one"
}

Cependant, Object.entries a un faible soutien en ce moment ne fonctionne pas dans IE ou iOS Safari. Vous aurez probablement besoin d'un polyfill.

28
mpen

Itérateur, Itérable et pour .. de la boucle dans ECMAScript 2015/ES6

let tempArray = [1,2,3,4,5];

for(element of tempArray) {
  console.log(element);
}

// 1
// 2
// 3
// 4
// 5

Mais si nous faisons

let tempObj = {a:1, b:2, c:3};

for(element of tempObj) {
   console.log(element);
}
// error

Nous obtenons une erreur parce que pour..de boucle ne fonctionne que sur Iterables , c'est-à-dire, l'objet qui a un @@ iterator qui adhère à protocole Iterator , ce qui signifie qu'il doit avoir un objet avec une méthode next . La méthode suivante ne prend aucun argument et doit renvoyer un objet avec ces deux propriétés.

done : indique que la séquence est terminée quand true et false signifie qu'il peut y avoir plus de valeurs value : il s'agit de l'élément en cours dans la séquence

Donc, faire un objet Iterable c’est le faire fonctionner avec pour..de nous pouvons:

1. Créez un objet avec un Iterable en lui attribuant un caractère mystique @@ iterator à l’aide de Symbol.iterator property.Voici comment:

let tempObj = {a:1, b:2, c:3};

tempObj[Symbol.iterator]= () => ({
next: function next () {
return {
    done: Object.keys(this).length === 0,
    value: Object.keys(this).shift()
     }
    }
  })

for(key in tempObj){
 console.log(key)
}
// a
// b
// c

2.Utilisez Object.entries , qui retourne un Iterable :

let tempObj = {a:1, b:2, c:3};

for(let [key, value] of Object.entries(tempObj)) {
    console.log(key, value);
}
// a 1
// b 2
// c 3

3.Utilisez Object.keys , voici comment:

let tempObj = {a:1, b:2, c:3};
for (let key of Object.keys(tempObj)) {
    console.log(key);
}

// a
// b
// c

J'espère que cela t'aides!!!!!!

18
Manishz90

Parce que le littéral d'objet n'a pas la propriété Symbol.iterator . Pour être plus précis, vous ne pouvez parcourir que String , Array , Map , Set , arguments , NodeList (pas largement pris en charge) et Générateur avec pour ... de boucle.

Pour traiter l'itération Object Literal, vous avez deux options.

pour ... dans

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

Object.keys + forEach

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

La réponse est non. Il n'est pas possible d'utiliser For..Of avec des littéraux d'objet. 

Je suis d'accord avec Overv que For..Of est uniquement pour iterables. J'avais exactement la même question parce que j'utilise des objets pour parcourir des clés et des valeurs avec for..in. Mais je viens de me rendre compte que c’est à quoi servent ES6 MAPS et ENSEMBLES

let test = new Map();
test.set('first', "one");
test.set('second', "two");

for(var item of test) {
  console.log(item); // "one" "two"
}

Par conséquent, l'objectif est de ne pas avoir à utiliser for..In (en validant avec hasOwnProperty) et de ne pas utiliser Object.keys (). 

De plus, vos clés ne sont pas limitées à des chaînes. Vous pouvez utiliser des nombres, des objets ou d'autres littéraux.

2
cuadraman

Les littéraux d'objet n'ont pas d'itérateurs intégrés, qui sont requis pour travailler avec des boucles for...of. Cependant, si vous ne souhaitez pas ajouter votre propre [Symbol.iterator] à votre objet, vous pouvez simplement utiliser la méthode Object.keys(). Cette méthode retourne un objet Array, qui a déjà un itérateur intégré, vous pouvez donc l'utiliser avec une boucle for...of comme celle-ci:

const myObject = {
    country: "Canada",
    province: "Quebec",
    city: "Montreal"
}

for (let i of Object.keys(myObject)) {
    console.log("Key:", i, "| Value:", myObject[i]);
}

//Key: country | Value: Canada
//Key: province | Value: Quebec
//Key: city | Value: Montreal
2
TheDarkIn1978

Il est possible de définir un itérateur sur n'importe quel objet donneur, ainsi vous pouvez mettre une logique différente pour chaque objet.

var x = { a: 1, b: 2, c: 3 }
x[Symbol.iterator] = function* (){
    yield 1;
    yield 'foo';
    yield 'last'
}

Ensuite, il suffit d'itérer directement x

for (let i in x){
    console.log(i);
}
//1
//foo
//last

Il est possible de faire la même chose sur l'objet Object.prototype et d'avoir un itérateur général pour tous les objets

Object.prototype[Symbol.iterator] = function*() {
    for(let key of Object.keys(this)) {
         yield key 
    } 
 }

alors itère ton objet comme ça

var t = {a :'foo', b : 'bar'}
for(let i of t){
    console.log(t[i]);
}

Ou de cette façon

var it = t[Symbol.iterator](), p;
while(p = it.next().value){
    console.log(t[p])
}
1
Yaki Klein

Je viens de faire ce qui suit pour consoler facilement mes affaires. 

for (let key in obj) {
  if(obj.hasOwnProperty(key){
    console.log(`${key}: ${obj[key]}`);
  }
}
1
DaFrenzy

En utilisant la destruction de tableaux, vous pouvez le parcourir comme suit en utilisant forEach

const obj = { a: 5, b: 7, c: 9 };

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

dans ES6, vous pouvez utiliser un générateur:

var obj = {1: 'a', 2: 'b'};

function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

let generator = entries(obj);

let step1 = generator.next();
let step2 = generator.next();
let step3 = generator.next();

console.log(JSON.stringify(step1)); // {"value":["1","a"],"done":false}
console.log(JSON.stringify(step2)); // {"value":["2","b"],"done":false}
console.log(JSON.stringify(step3)); // {"done":true}

Voici le jsfiddle. Dans la sortie, vous obtiendrez un objet avec les touches "value" et "done". "Value" contient tout ce que vous voulez qu'il ait et "done" est l'état actuel de l'itération dans bool.

0
Serge Nikolaev

Pourquoi ne pas utiliser Object.keys pour obtenir un tableau de clés? Et ensuite pour chaque sur le tableau ?

obj = { a: 1, b:2}
Object.keys(obj).forEach( key => console.log(`${key} => ${obj[key]}`))
0
justingordon

Qu'en est-il de l'utilisation

function* entries(obj) {
    for (let key of Object.keys(obj)) {
        yield [key, obj[key]];
    }
}

for ([key, value] of entries({a: "1", b: "2"})) {
    console.log(key + " " + value);
}
0
user1703761