2010-07-06 5 views
24

J'ai remarqué que certains codes qui évaluent certaines tailles de chaussures pour un site de commerce électronique et les affichent à l'écran gâchent la commande dans Chrome.Clés de réapprovisionnement des objets en chrome si les chiffres sont normaux/attendus

JSON donné peut être:

{ 
    "7": ["9149", "9139", "10455", "17208"], 
    "7.5": ["9140", "9150", "10456", "17209"], 
    "8": ["2684", "9141", "10457", "17210"], 
    "8.5": ["9142", "10444", "10458", "17211"], 
    "9": ["2685", "9143", "10459", "17212"], 
    "9.5": ["10443", "9144", "10460", "17213"] 
} 

... qui incrémente la taille en deux.

Lors de la conversion en un objet et itérer si les clés, l'ordre naturel est respecté et ils viennent comme:

7, 7.5, 8, 8.5, etc.

Mais Chrome seulement, les clés que 'look' comme les numéros ronds TOUJOURS sORTENT de l'objet premier, donc la sortie d'une boucle for ... in est:

7, 8, 9, 7. 5, 8,5, 9,5 ...

Object.keys(sizes); // ["7", "8", "9", "7.5", "8.5", "9.5"] 

est ici le cas de test: https://jsfiddle.net/wcapc46L/1/

Il est seulement affecte des nombres entiers, semble comme Webkit/Blink ont ​​une optimisation qui préfère propriétés d'objets qui sont numérique, peut-être que cela a à voir avec la prédiction de branche ou autre.

Si vous préfixer les clés d'objet avec un caractère, l'ordre reste inchangé et fonctionne comme prévu - FIFO

Je pense que je me souviens avoir lu qu'il n'y a aucune garantie sur l'ordre des propriétés d'un objet, mais en même Dans le temps, c'est énervant à l'extrême et cela causerait beaucoup d'efforts pour le fixer uniquement pour les utilisateurs de chrome.

Des idées? Est-ce probablement un bug qui sera corrigé?

modifier En outre, j'ai maintenant découvert cela comme un problème sur le bug v8 Tracker:

http://code.google.com/p/v8/issues/detail?id=164

Ressemble Blink ne veulent pas résoudre ce problème et restera le seul navigateur qui fais le.

mise à jour quelle que soit l'optimisation de la table de hachage webkit/blink avait, a fait son chemin dans gecko (FF 27.0.1) - http://jsfiddle.net/9Htmq/ résultats dans 7,8,9,7.5,8.5,9.5. l'application _ avant que les clés retourne l'ordre correct/prévu.

mise à jour 2017 Les gens sont encore upvoting et l'édition de cette façon - Il ne semble pas affecter Map/WeakMap, Set etc (comme l'a démontré par l'exemple principal mis à jour)

+0

+1 pour un test élémentaire. – spender

+4

Je pense que vous devez réorganiser votre méthode de planification ici. Si vous avez * lu * que la commande n'est pas définie, pourquoi vous plaignez-vous de devoir corriger beaucoup de code lorsque vous découvrez que * surprise surprise *, elle est indéfinie? Ce n'est pas un bogue qui sera corrigé, d'autres pour dire que le bogue est dans votre code, vous vous êtes fié aux détails de l'implémentation, pas au comportement documenté. Fixe ton code. –

+1

au moment du développement, le chrome était loin d'être atteint et représente maintenant 7% des utilisateurs du site. jusqu'à ce que le chrome arrive, il a fonctionné comme prévu dans tous les navigateurs, safari inclus - donc ce n'est pas un problème de webkit.et oui, je comprends qu'il peut avoir besoin de refactorisation mais espérait une solution plus facile (ou que le chrome sera en train de régler cela comme tout le monde). pour l'instant, je peux devoir préfixer toutes les propriétés d'objet avec __ ou quelque chose pour forcer l'ordre naturel de définition. –

Répondre

20

C'est la façon dont v8 gère les tableaux associatifs. Un numéro connu Issue 164 mais il suit la spécification ainsi est marqué «fonctionnant comme prévu». Il n'y a pas d'ordre requis pour faire une boucle dans les tableaux associatifs.

Une solution simple consiste à précéder les valeurs numériques avec des lettres par exemple: 'size_7':['9149','9139'] etc.

Les développeurs standards changera dans la spécification suivante ECMAScript forçant [chrome] pour changer cette situation.

+1

changement en faveur de la mise en œuvre actuelle de chrome ou en faveur de la préservation de l'ordre de la définition? –

+2

préserver la commande puisque tous les autres navigateurs le font déjà. –

+0

super nouvelles! Merci beaucoup. –

1

Il semblerait que Chrome traite le entier chaîne comme s'il s'agissait d'un type numérique lorsqu'il est utilisé comme nom d'index/propriété. Je pense que s'appuyer sur l'implémentation Javascript pour préserver l'ordre de ce qui, dans certains cas, est des propriétés d'objet, et dans d'autres cas (certainement avec chrome), est une approche dangereuse et l'ordre de dénombrement n'est probablement pas défini dans la spécification. Je suggère d'ajouter une propriété supplémentaire au JSON qui indique un ordre de tri:

{ 
    "7":{"sortOrder":1,"data":["9149","9139","10455","17208"]}, 
    "7.5":{"sortOrder":2,"data":["9140","9150","10456","17209"]} 
    //etc 
} 
+0

qui peut fonctionner - je peux appliquer un filtre qui vérifie la propriété sortOrder lors de la boucle et injecte les éléments en conséquence dans le DOM. –

0

Je ne pense pas que vous pouvez appeler cela un bug. Comme vous le dites vous-même, il n'y a aucune garantie sur la façon dont les propriétés d'un objet sont triées.

+0

Et ce n'est pas une réponse. –

1

Ils sont traités comme des chaînes car ils sont des chaînes. Ma meilleure suggestion serait d'utiliser la même "précision" dans toutes vos clés.

{"7.0":["9149","9139","10455","17208"],"7.5":["9140","9150","10456","17209"],"8.0":["2684","9141","10457","17210"],"8.5":["9142","10444","10458","17211"],"9.0":["2685","9143","10459","17212"],"9.5":["10443","9144","10460","17213"]} 

Ainsi, « 8,0 » au lieu de « 8 », etc.

Même alors, il n'y a aucune garantie, mais il est plus probable qu'ils sortent dans le même ordre. Pour une meilleure garantie, effectuez un tri en fonction des clés, en plaçant les valeurs dans un tableau dans l'ordre trié.

+0

malheureusement, même si cela fonctionnera pour le cas de test, ce ne sera pas une option pour la mise en œuvre. les tailles sont une multitude de différentes options, telles que 'S, M, L, XL, XXL 'ou '44, 44.5,44.5' ou 'One Size' et ainsi de suite, tel que défini par produit par le marchand. Il y a énormément de logique dans le tri de la sortie de MYSQL afin qu'il arrive dans le bon ordre et non pas en tant que chaînes - il couvre quelque chose comme 40 tailles distinctes pré-définies dans l'ordre de préférence. –

1

Lorsque itérer sur les propriétés d'un objet, l'ordre est spécifié dans la spécification ECMAScript comme étant définie et l'ordre que vous avez peut-être observé dans un certain environnement ne devrait pas être invoquée. Si vous avez besoin d'une commande, utilisez un Array.

0

J'ai trouvé un travail facile autour de l'aide underscore.js

myArray = _.sortBy(myArray, function(num){ return Math.ceil(num); }); 

Yay! myArray est de retour dans le bon ordre dans tous les navigateurs.

Questions connexes