chromeは、数値の場合、オブジェクトキーを再注文することは、その通常/期待されるものです

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

質問

eコマースサイトの靴のサイズを評価し、画面に出力する特定のコードがChromeで注文を台無しにしていることに気付きました。

与えられたjsonは次のようになります:

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

...半分のサイズを増加させます。

オブジェクトに変換され、キーを繰り返すと、自然な秩序が尊重されており、次のように出てきます。

7、7.5、8、8.5など

しかし、クロムのみでは、丸い数字のように「見える」キー いつも 最初にオブジェクトから出てくるので、forの出力...ループは次のとおりです。

7, 8, 9, 7.5, 8.5, 9.5 ...

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

これがテストケースです: https://jsfiddle.net/wcapc46l/1/

それは整数にのみ影響し、WebKit / Blinkには最適化があるようです 好む 数値のオブジェクトプロパティ、おそらくそれはブランチの予測などに関係するかもしれません。

オブジェクトキーに任意の文字をプレフィックスすると、順序は影響を受けず、意図したとおりに機能します-FIFO

オブジェクトのプロパティの順序には保証はないが、同時にこれは極端に迷惑であり、Chromeユーザーだけでそれを修正するのにかなりの努力をもたらすだろうと読んだことを思い出したと思います。

何か案は?これはおそらく修正されるバグですか?

編集 さらに、これをV8バグトラッカーの問題として発見しました。

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

Blinkはこれを修正したくないように見え、それを行う唯一のブラウザのままです。

アップデート WebKit/Blinkが持っていたハッシュテーブルの最適化が何であれ、Gecko(FF 27.0.1)に進出しました - http://jsfiddle.net/9htmq/ 結果 7,8,9,7.5,8.5,9.5. 。申請中 _ キーが正しい /予想される順序を返す前に。

更新2017 人々はまだこれを支持して編集しているので、それは影響しないようです Map / WeakMap, Set など(更新されたメインの例で示されているように)

役に立ちましたか?

解決

これは、V8が連想配列を処理する方法です。既知の問題 第164号 しかし、それは仕様に従うため、「意図したとおりに動作する」とマークされています。連想配列をループするために必要な注文はありません。

単純な回避策は、文字を使用して数値の値に先行することです。 'size_7':['9149','9139']

標準は、[Chrome]開発者がこれを変更するように強制する次のECMAScript仕様で変更されます。

他のヒント

Chromeが治療しているように見えます 整数 文字列は、インデックス/プロパティ名として使用された場合の数値タイプであるかのように。

JavaScriptの実装に依存して、場合によってはオブジェクトのプロパティであるものの順序を維持すると思います。 。ソートオーダーを示すJSONに追加のプロパティを追加することをお勧めします。

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

彼らは彼らが弦として扱われています それは 文字列。私の最善の提案は、すべての鍵で同じ「精度」を使用することです。

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

したがって、「8」の代わりに「8.0」など

それでも、保証はありませんが、同じ順序で出てくる可能性が高くなります。

より良い保証のために、キーに基づいてソートを実行し、ソートされた順序で値を配列に入れます。

オブジェクトのプロパティを反復する場合、順序はECMAScriptの仕様で定義されていないものとして指定され、一部の環境で観察された順序は依存してはなりません。注文が必要な場合は、anを使用してください Array.

これをバグと呼ぶことはできないと思います。あなたが自分自身を言うように、オブジェクトのプロパティがどのようにソートされているかについてのガランティはありません。

underscore.jsを使用して簡単な回避を見つけました

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

わーい! MyArrayは、すべてのブラウザで正しい順序に戻りました。

私の鍵は、私がそれらをひもに変換するにはあまりにも重要でした。代わりに、キーの順序を維持したばかりの別の配列を作成しました。

<?php 
$origArray = valueReturnedFromFunction();
$preservedOrder = array_keys($origArray);
?>
<script>
var origArray = <?php echo json_encode($origArray)?>;
var preservedOrder = <?php echo json_encode($preservedOrder )?>;

for(i in preservedOrder){
    var item = origArray[i];
    ...
}
</script>
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top