2010-07-06 6 views
24

Ich bemerkte, dass bestimmte Code, der einige Schuhgrößen für eine E-Commerce-Website bewertet und auf dem Bildschirm ausgibt, die Reihenfolge in Chrome versaut.Chrome Nachbestellen Objektschlüssel, wenn Numerik, ist das normal/erwartet

JSON kann gegeben sein:

{ 
    "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"] 
} 

... die Größen in Hälften erhöht.

Bei der Umwandlung in ein Objekt und Iterieren obwohl der Schlüssel, die natürliche Ordnung eingehalten wird und sie kommt wie:

7, 7.5, 8, 8.5 usw.

Aber in Chrom nur, Tasten, die 'Look' wie runde Zahlen ALWAYS aus dem Objekt kommen zuerst, so Ausgang einer for ... in Schleife ist:

7, 8, 9, 7. 5, 8.5, 9.5 ...

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

Hier ist der Testfall: https://jsfiddle.net/wcapc46L/1/

Es nur ganze Zahlen beeinflusst ist, scheint wie Webkit/Blink eine Optimierung, die Objekteigenschaften bevorzugt, die numerisch, vielleicht ist es mit der Branch Prediction oder was auch immer zu tun.

Wenn Sie die Objektschlüssel mit einem beliebigen Zeichen Präfix, bleibt die Reihenfolge nicht betroffen und funktioniert wie beabsichtigt - FIFO

Ich glaube, ich erinnere lesen, dass es keine Garantien in der Größenordnung von Eigenschaften eines Objekts, aber gleichzeitig Diese Zeit ist extrem ärgerlich und würde einen erheblichen Aufwand bei der Behebung von Chrome-Benutzern verursachen.

Irgendwelche Ideen? ist das wahrscheinlich ein Bug, der behoben wird?

bearbeiten zusätzlich habe ich entdeckt, jetzt dies als ein Problem auf dem Tracker v8 Fehler:

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

wie Blink Sieht nicht will, dies zu beheben und den einzigen Browser bleiben, das wird TU es.

Update was Hash-Tabelle Optimierung webkit/blink hatte, hat nun seinen Weg in Gecko (FF 27.0.1) gemacht - http://jsfiddle.net/9Htmq/ Ergebnisse in 7,8,9,7.5,8.5,9.5. Anwendung _, bevor die Schlüssel die richtige/erwartete Reihenfolge zurückgibt.

Update 2017 Menschen sind immer noch upvoting und bearbeite diese so - es ist nicht Map/WeakMap, Set usw. zu beeinflussen scheint (wie durch aktualisierte Haupt Beispiel gezeigt)

+0

+1 für einen Testfall. – spender

+4

Ich denke, Sie müssen hier Ihre Methode der Planung neu anordnen. Wenn Sie * gelesen * haben, dass die Reihenfolge nicht definiert ist, warum beschweren Sie sich, dass Sie viel Code reparieren müssen, wenn Sie jetzt diese * Überraschungsüberraschung * entdecken, es ist undefiniert? Dies ist kein Fehler, der behoben wird. Anders gesagt, der Fehler befindet sich in Ihrem Code, Sie haben sich auf Implementierungsdetails verlassen und nicht auf dokumentiertes Verhalten. Korrigieren Sie Ihren Code. –

+1

zum Zeitpunkt der Entwicklung, Chrom war nicht annähernd und es beläuft sich jetzt auf 7% der Website-Nutzer. bis chrome kam, funktionierte es wie geplant in allen browsern, inklusive safari - also kein webkit-problem.und ja, ich verstehe, dass es Refactoring benötigt, aber hoffte auf eine einfachere Lösung (oder dass Chrome wird dies tatsächlich reparieren wie jeder andere). Für den Moment muss ich vielleicht allen Objekteigenschaften mit __ oder etwas vorangestellt werden, um die natürliche Reihenfolge der Definition zu erzwingen. –

Antwort

20

So behandelt v8 assoziative Arrays. Ein bekanntes Problem Issue 164, aber es folgt der Spezifikation, so ist markiert "funktioniert wie vorgesehen". Es gibt keine erforderliche Reihenfolge für das Durchlaufen assoziativer Arrays.

Eine einfache Lösung wäre es, Zahlenwerte mit Buchstaben z vorangehen: 'size_7':['9149','9139'] usw.

Der Standard wird in der nächsten ECMAScript-Spezifikation ändern zwingen [Chrom] Entwickler, dies zu ändern.

+1

Änderung zugunsten der aktuellen Implementierung von Chrome oder zugunsten der Reihenfolge der Definition zu bewahren? –

+2

die Reihenfolge beibehalten, da alle anderen Browser dies bereits tun. –

+0

tolle Neuigkeiten! Danke vielmals. –

1

Es scheint, dass Chrome behandelt Die Ganzzahl Zeichenfolge, als ob es ein numerischer Typ wäre, wenn sie als Index/Eigenschaftenname verwendet wird.

Ich denke, auf die Javascript-Implementierung angewiesen, um die Reihenfolge zu erhalten, was in einigen Fällen Objekteigenschaften ist, und in anderen Fällen (sicherlich mit Chrom) Array-Indizes, ist nachweislich eine unsichere Vorgehensweise und Reihenfolge der Aufzählung ist wahrscheinlich nicht in der Spezifikation definiert. Ich würde vorschlagen, eine zusätzliche Eigenschaft zum JSON hinzufügen, die eine Sortierreihenfolge angibt:

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

das kann funktionieren - ich kann einen Filter anwenden, der SortOrder-Eigenschaft beim Schleifen überprüft und die Elemente entsprechend in das DOM injiziert. –

0

Ich glaube nicht, dass Sie dies ein Fehler nennen. Wie Sie selbst sagen, gibt es keine Garantie, wie die Eigenschaften eines Objekts sortiert werden.

+0

Und das ist keine Antwort. –

1

Sie werden als Strings behandelt, weil sie Strings sind. Mein bester Vorschlag wäre, die gleiche "Präzision" in allen Ihren Schlüsseln zu verwenden.

{"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"]} 

Also „8.0“ anstelle von „8“ usw.

Selbst dann gibt es keine Garantien, aber es ist wahrscheinlicher, dass sie in der gleichen Reihenfolge herauskommen werden.

Um eine bessere Garantie zu erhalten, führen Sie eine Sortierung basierend auf den Schlüsseln durch, indem Sie die Werte in einem Array in der sortierten Reihenfolge platzieren.

+0

Bedauerlicherweise wird dies, obwohl dies für den Testfall funktionieren wird, keine Option für die Implementierung sein. Größen sind eine Vielzahl von verschiedenen Optionen, wie zum Beispiel "S, M, L, XL, XXL" oder "44, 44.5, 44.5" oder "One Size" und so weiter, wie auf einer Pro-Produkt-Basis vom Händler definiert. Es gibt eine enorme Logik, die beim Sortieren der Ausgabe von MYSQL eine Rolle spielt, so dass sie in der richtigen Reihenfolge und nicht als Zeichenfolgen ankommt - sie umfasst etwa 40 separate Größen, die in der Reihenfolge ihrer Präferenz vordefiniert sind. –

1

Wenn Sie über die Eigenschaften eines Objekts iterieren, wird die Reihenfolge in der ECMAScript-Spezifikation als nicht definiert angegeben und jede Reihenfolge, die Sie in einer bestimmten Umgebung beobachtet haben, sollte nicht verlässlich sein. Wenn Sie eine Bestellung benötigen, verwenden Sie eine Array.

0

fand ich eine einfache Arbeit um mit Underscore.js

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

Yay! myArray ist wieder in der richtigen Reihenfolge in allen Browsern.

Verwandte Themen