Chrome повторно заказывает клавиши объектов, если числовые средства, это нормально / ожидается

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

Вопрос

Я заметил, что определенный код, который оценивает некоторые размеры обуви для сайта электронной коммерции и выводит их на экране, восстает порядок в 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 и т. Д.

Но только в Chrome, клавиши, которые «выглядят» как круглые номера ВСЕГДА Сначала выходите из объекта, поэтому вывод A для ... в цикле:

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, теперь пробился в геккон (FF 27.0.1) - http://jsfiddle.net/9htmq/ приводит к 7,8,9,7.5,8.5,9.5. Отказ подать заявку _ До того, как ключи возвращают правильный / ожидаемый заказ.

Обновление 2017 года Люди все еще уходят и редактируют это так - оно не влияет на Map / WeakMap, Set etc (как продемонстрировано обновленным основным примером)

Это было полезно?

Решение

Это так, как V8 обрабатывает ассоциативные массивы. Известный вопрос Выпуск 164. Но следует, что Spec так отмечается «работает как предназначено». Не требуется не требуемый порядок для обработки ассоциативных массивов.

Простой обходной путь должен предшествовать значениям номера с буквами, например: 'size_7':['9149','9139'] и т. д.

Стандарт будет изменяться в следующем Secmascript Spect Specting [Chrome] разработчиков, чтобы изменить это.

Другие советы

Похоже, что Chrome относится к целое число строка, как будто это был числовой тип при использовании в качестве имени индекса / свойства.

Я думаю, что полагается на реализацию JavaScript, чтобы сохранить порядок того, что в некоторых случаях является объектом свойства, а в других случаях (безусловно, с Chrome) индексов массива, пожалуй, небезопасный подход и порядок перечисления, вероятно, не определен в спецификации Отказ Я бы предложил добавить дополнительное свойство 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,0» вместо «8» и т. Д.

Даже тогда нет никаких гарантий, но скорее всего, они выйдут в том же порядке.

Для лучшего гарантии выполните сортирование на основе ключей, вкладывая значения в массив в отсортированном порядке.

При итерации по свойствам объекта порядок указан в спецификации Ecmascript как не определено, и любой порядок, на который вы, возможно, наблюдали в некоторой среде, не должны быть полагаться. Если вам нужен заказ, используйте 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