Ordre des éléments dans un & # 8220; pour (& # 8230; à & # 8230;) & # 8221; boucle

StackOverflow https://stackoverflow.com/questions/280713

  •  07-07-2019
  •  | 
  •  

Question

Le " for… in " boucle en Javascript boucle à travers les hashtables / éléments dans l'ordre dans lequel 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 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 à "A:" Bonjour " toujours venir avant 'B: "Monde" dans la plupart des navigateurs décents?

Était-ce utile?

La solution

Citer John Resig :

  

Actuellement, tous les principaux navigateurs parcourent les propriétés d’un objet dans l’ordre suivant:   qui ils ont été définis. Chrome le fait également, sauf dans quelques cas. [...]   Ce comportement est explicitement laissé indéfini par la spécification ECMAScript.   Dans l'ECMA-262, section 12.6.4:

     
    

La mécanique d'énumération des propriétés ... dépend de la mise en œuvre.

  
     

Cependant, la spécification est assez différente de la mise en oeuvre. Toutes les implémentations modernes   de ECMAScript itérer à travers les propriétés d'objet dans l'ordre dans lequel elles ont été définies.   Pour cette raison, l'équipe de Chrome a estimé qu'il s'agissait d'un bug et le corrigera.

Tous les navigateurs respectent l'ordre de définition à l'exception de Chrome . et Opera qui font pour chaque nom de propriété non numérique. Dans ces deux navigateurs, les propriétés sont placées dans l'ordre devant la première propriété non numérique (cela concerne la façon dont elles implémentent les tableaux). La commande est la même pour Object.keys .

Cet exemple devrait indiquer clairement 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 sont moins importants que le fait que cela peut changer à tout moment. Ne comptez pas sur les choses qui restent ainsi.

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

Autres conseils

Bumping this un an plus tard ...

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

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

Gist ou à tester dans le navigateur actuel

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] 

Extrait de la spécification du langage ECMAScript , section 12.6.4 (sur la pour la boucle .. dans ):

  

La mécanique d'énumération des propriétés dépend de la mise en œuvre. L'ordre d'énumération est défini par l'objet.

Et section 4.3.3 (définition de "objet"):

  

Il s'agit d'une collection non ordonnée de propriétés, chacune contenant une valeur primitive, un objet ou une fonction. Une fonction stockée dans une propriété d'un objet s'appelle une 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 pour toutes les implémentations JavaScript. (De toute façon, ce serait un mauvais style de s’appuyer sur les détails d’un langage spécifiques à l’implémentation.)

Si vous souhaitez que votre commande soit définie, vous devez implémenter quelque chose qui la définit, comme un tableau de clés que vous triez avant d'accéder à l'objet avec elle.

Les éléments d'un objet énumérés pour / dans sont les propriétés pour lesquelles l'indicateur DontEnum n'est pas défini. Le standard ECMAScript, également appelé Javascript, indique 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).

Cela ne va pas être conforme aux normes (c'est-à-dire sans danger) d'assumer que toutes les implémentations Javascript énuméreront dans l'ordre des déclarations.

L'ordre des itérations est également confus en ce qui concerne la suppression des 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 les spécifications pour corriger l'ordre d'itération semble être un désir très répandu parmi les développeurs si la discussion à http://code.google.com/p/v8/issues/detail?id=164 est une indication quelconque.

dans IE6, la commande n’est pas garantie.

La commande ne peut pas être approuvée. Opera et Chrome renvoient tous deux la liste des propriétés non ordonnées.

<script type="text/javascript">
var username = {"14719":"A","648":"B","15185":"C"};

for (var i in username) {
  window.alert(i + ' => ' + username[i]);
}
</script>

Le code ci-dessus indique B, A, C dans Opera et C, A, B dans Chrome.

Cela ne répond pas à la question en soi, mais offre une solution au problème de base.

En supposant que vous ne pouvez pas compter sur l'ordre pour préserver, pourquoi ne pas utiliser un tableau d'objets avec la clé et la valeur en tant que propriétés?

var myArray = [
    {
        'key'   : 'key1'
        'value' : 0
    },
    {
        'key'   : 'key2',
        'value' : 1
    } // ...
];

Maintenant, il vous appartient de vous assurer que les clés sont uniques (en supposant que cela soit également important pour vous. En outre, les modifications d'adresse directe et pour (... dans ...) renvoie désormais les index sous la forme ' touches '.

> console.log(myArray[0].key);
key1

> for (let index in myArray) {console.log(myArray[index].value);}
0
1
Voir le stylo pour l'adressage (... dans ...) dans l'ordre par JDQ ( @JDQ ) sur CodePen .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top