J'ai besoin de parcourir un objet JavaScript en le traitant comme un tableau avec des clés personnalisées. Je sais que cela n'est pas entièrement pris en charge, car les propriétés n'ont pas d'ordre intrinsèque, mais comme je réorganise toujours les propriétés, j'ai trouvé cette approche simple et fiable ... jusqu'à présent.
Le problème se produit lorsque les clés sont des nombres ou des chaînes pouvant être converties en nombres.
Lorsque j'exécute ce code:
var test1 = {4294966222:"A",4294966333:"A",4294966111:"A"};
var test2 = {4294968222:"A",4294968333:"A",4294968111:"A"};
for (var k in test1) {console.log(k);}
console.log("---");
for (var k in test2) {console.log(k);}
la sortie est:
4294966111
4294966222
4294966333
---
4294968222
4294968333
4294968111
Ce qui signifie:
- (test1) si les touches sont inférieures à 2 ^ 32 (4 294 967 296), elles sont automatiquement réorganisées, la plus petite en premier
- (test2) si les touches sont supérieures à 2 ^ 32, elles ne sont PAS réorganisées.
La question est: pourquoi cela se produit-il?
Étant donné que tous les navigateurs que j'ai testés (Google Chrome 79.0, Mozilla Firefox 71.0, Microsoft Edge 44.18362, Internet Explorer 11.535) sont d'accord sur cette sortie, il doit y avoir des spécifications officielles.
Mise à jour
J'ai testé beaucoup de chiffres avant de découvrir que c'était une question de seuil. J'ai trouvé étrange que la séquence 2,3,1 se comporte différemment de trois horodatages ordonnés de la même manière.
la source
test1
ettest2
. Je pense que le "problème" vient de la mise en cache des clés dans la mise en œuvre V8 de la spécification.4294968333
et4294968111
sont supérieures à2 ** 32
(ce qui est4294967296
). Donc, ce ne sont pas des indices de tableau, ils sont donc itérés dans l'ordre de création des propriétés plutôt que dans l'ordre numérique croissant - ce qui est exactement ce qu'ils font au violon, comme prévu. (voir ma réponse)Réponses:
C'est attendu. Selon la spécification , la méthode qui itère sur les propriétés,,
OrdinaryOwnPropertyKeys
fait:L'ordre numérique croissant ne s'applique qu'aux propriétés qui sont des indices de tableau.
Alors, qu'est-ce qu'un "index de tableau"? Cherchez ::
Ainsi, les propriétés numériques supérieures à 2 ^ 32 ne sont pas des indices de tableau et sont donc itérées dans l'ordre de création des propriétés. Toutefois, les propriétés numériques qui sont moins
2^32
sont indicies de tableau et sont itéré par ordre numérique croissant.Ainsi, par exemple:
1
: Index de tableau, sera itéré numériquement10
: Index de tableau, sera itéré numériquement4294968111
: Supérieur à2 ** 32
, sera réitéré après la fin des indices du tableau, dans l'ordre de création des propriétés9999999999999
: Supérieur à2 ** 32
, sera réitéré après la fin des indices du tableau, dans l'ordre de création des propriétésDe plus, gardez à l'esprit que, contrairement à la croyance populaire, l'ordre d'itération des propriétés est également garanti par la spécification, grâce à la proposition d'itération for-in qui est l'étape 4.
la source
Cela a à voir avec la façon dont les clés d'un objet sont traversées.
Selon les spécifications ES6, il devrait être:
http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
Cela signifie que si la valeur d'une clé reste la même si elle est convertie en un nombre non signé de 53 bits et en arrière, elle est traitée comme un index entier qui est trié par ordre numérique croissant.
Si cela échoue, il est traité comme une clé de chaîne, qui est ordonnée de la façon dont elle a été ajoutée à l'objet.
Le hic ici est que tous les principaux navigateurs ne suivent pas encore cette spécification et utilisent à la place un index de tableau qui est limité à un nombre positif jusqu'à . Donc, tout ce qui dépasse cette limite est en fait une clé de chaîne.
la source