215 votes

Commande d'éléments dans une boucle "for (... in ...)"

Est-ce que la boucle "for ... in" en Javascript parcourt les hashtables / éléments dans l'ordre où ils sont déclarés? Y a-t-il un navigateur qui ne le fait pas dans l'ordre?
L'objet que je souhaite utiliser sera déclaré une seule fois et ne sera jamais modifié.

Supposons que j'ai:

 var myObject = { A: "Hello", B: "World" };
 

Et je les utilise également dans:

 for (var item in myObject) alert(item + " : " + myObject[item]);
 

Puis-je m'attendre à ce que 'A: "Hello"' arrive toujours avant 'B: "World"' dans les navigateurs les plus décents?

221voto

Borgar Points 12493

Citant John Resig:

Actuellement, tous les grands navigateurs de la boucle sur les propriétés d'un objet dans l'ordre lequel elles ont été définies. Chrome le fait aussi bien, à l'exception de quelques cas. [...] Ce comportement est explicitement pas défini par la spécification ECMAScript. ECMA-262, section 12.6.4:

La mécanique de l'énumération des propriétés ... est dépendant de l'implémentation.

Toutefois, la spécification est tout à fait différente de la mise en œuvre. Toutes les implémentations modernes d'ECMAScript itérer sur les propriétés de l'objet dans l'ordre dans lequel elles ont été définies. Pour cette raison, le Chrome, l'équipe a jugé que ce soit un bug et de le réparer.

Tous les navigateurs le respect de la définition de l'ordre à l'exception de Chrome et Opéra le faire pour tous les non-numérique nom de la propriété. Dans ces deux navigateurs les propriétés sont tirés dans l'ordre avant que le premier non-numériques de propriété (c'est a faire avec la façon dont ils mettent en œuvre des tableaux). L'ordre est le même pour Object.keys .

Cet exemple devrait le rendre clair ce qui se passe:

var obj = {
  "first":"first",
  "2":"2",
  "34":"34",
  "1":"1",
  "second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"

Les détails techniques de ce sont moins important que le fait que cela peut changer à tout moment. Ne comptez pas sur les choses et de rester de cette façon.

En bref: Utiliser un tableau si l'ordre est important pour vous.

54voto

dvdrtrgn Points 646

Cogner un an plus tard ...

Il est 2012 et les principaux navigateurs diffèrent encore:

 function lineate(obj){
    var arr = [], i;
    for (i in obj) arr.push([i,obj[i]].join(':'));
    console.log(arr);
}
var obj = { a:1, b:2, c:3, "123":'xyz' };
/* log1 */  lineate(obj);
obj.a = 4;
/* log2 */  lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */  lineate(obj);
 

essentiel

Safari 5, Firefox 14

 ["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]
 

Chrome 21, Opera 12, Node 0.6, Firefox 27

 ["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]
 

IE9

 [123:xyz,a:1,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 
 

28voto

Tomalak Points 150423

À partir de la Spécification du Langage ECMAScript, section 12.6.4 (sur l' for .. in boucle):

La mécanique de l'énumération des propriétés est dépendant de l'implémentation. L'ordre d'énumération est défini par l'objet.

Et la section 4.3.3 (définition du terme "Objet"):

C'est une collection non ordonnée de propriétés qui contiennent chacune une valeur primitive, de l'objet ou de la fonction. Une fonction stockée dans une propriété d'un objet est appelée la méthode.

Je suppose que cela signifie que vous ne pouvez pas compter sur les propriétés énumérées dans un ordre cohérent à travers les implémentations JavaScript. (Il serait mauvais style de toute façon compter sur la mise en œuvre des détails spécifiques d'une langue.)

Si vous voulez que votre ordre défini, vous aurez besoin de mettre en place quelque chose qui se définit, comme un tableau de clés de tri avant d'accéder à l'objet.

10voto

Adam Wright Points 31715

Les éléments d'un objet que / en énumère sont les propriétés qui n'ont pas l'indicateur DontEnum défini. L'ECMAScript, alias Javascript, standard dit explicitement que "Un objet est une collection non ordonnée de propriétés" (voir http://www.mozilla.org/js/language/E262-3.pdf section 8.6).

Il ne sera pas conforme aux normes (c'est-à-dire sûr) de supposer que toutes les implémentations Javascript seront énumérées dans l'ordre de déclaration.

5voto

Brett Zamir Points 5355

L'ordre d'itération est également confondu avec la suppression de propriétés, mais dans ce cas avec IE uniquement.

 var obj = {};
obj.a = 'a';
obj.b = 'b';
obj.c = 'c';

// IE allows the value to be deleted...
delete obj.b;

// ...but remembers the old position if it is added back later
obj.b = 'bb';
for (var p in obj) {
    alert(obj[p]); // in IE, will be a, bb, then c;
                   // not a, c, then bb as for FF/Chrome/Opera/Safari
}
 

Le désir de modifier la spécification pour corriger l'ordre d'itération semble être un désir très populaire parmi les développeurs si la discussion à http://code.google.com/p/v8/issues/detail?id=164 est une indication.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X