Итерирование свойств объекта JavaScript и массивов с for..in, когда упорядочение важно - PullRequest
3 голосов
/ 26 июня 2010

Это был старый вопрос , и мне известны обычные причины не использовать for..in или, возможно, даже объекты, когда требуется какой-либо порядок, но я недавно натолкнулся на эту статью из MDC в операторе удаления.

Кросс-браузерные проблемы

Хотя ECMAScript делает порядок итераций объектов зависимым от реализации, может показаться, что все основные браузеры поддерживаютпорядок итераций, основанный на самом раннем добавленном свойстве, которое идет первым (по крайней мере, для свойств, не относящихся к прототипу).Тем не менее, в случае Internet Explorer, когда кто-то использует delete для свойства, возникает некоторое запутанное поведение, не позволяющее другим браузерам использовать простые объекты, такие как литералы объектов, в качестве упорядоченных ассоциативных массивов.В Проводнике, хотя значение свойства действительно установлено как неопределенное, если позднее оно добавит свойство с тем же именем, свойство будет повторяться в его старой позиции, а не в конце последовательности итерации, как можно было ожидать после того, какудалил свойство, а затем добавил его обратно.

Поэтому, если вы хотите смоделировать упорядоченный ассоциативный массив в кросс-браузерной среде, вы вынуждены либо использовать два отдельных массива (один для ключей, а другой длязначения), или создать массив объектов с одним свойством и т. д.

Похоже, что большинство основных браузеров - Chrome, Safari, Firefox и Opera перечисляют свойства объекта в порядке вставки.Это быстрый тест , чтобы подтвердить это.Это может не работать в IE, но у меня нет доступа к IE, чтобы проверить это, к сожалению.Так же IE сохраняет порядок (6/7 и далее) при переборе свойств, используя for..in, предполагая, что мы ничего не удаляем из объекта?

Также for..in никогда рекомендуется для итерации массивов по тем же причинам, а также тот факт, что Array.prototype чаще подделывают, чем Object.prototype.Однако, если свойства фактически были перечислены в порядке вставки, то, я полагаю, for..in можно использовать и для циклического перебора массивов, при этом будет указано следующее свойство: свойства, перечисленные в Array.prototype, будут также перечислены.

Для этого есть два решения:

Проверьте, принадлежит ли свойство объекту, используя hasOwnProperty

for(var index in object) {
    if(object.hasOwnProperty(index)) {
        ..
    }
}

Используйте новый синтаксис ES5 для определения свойств объектов и сделайте их не перечисляемыми.Это предполагает, что у вас есть полный контроль над расширением базовых прототипов, и никакой сторонний код не добавляет ничего непосредственно к прототипу.

Object.defineProperty(Array.prototype, "size", {
    enumerable: false,
    configurable: false,
    get: function() { return this.length; },
    set: undefined
});

Если все вышеперечисленные условия выполнены, и если я не пропускаю что-то важноеfor..in можно безопасно использовать и для итерации массива:

var values = [1, 2, 3];

for(var i in values) {
    values[i];
}

Так что я думаю, что это вернулось к первоначальному вопросу.Независимо от того, что спецификация говорит, IE поддерживает итерацию объекта в порядке вставки, для любых версий?Существуют ли другие браузеры, которые также не поддерживают это.

Ответы [ 3 ]

4 голосов
/ 05 июля 2010

Тесты в IE 5.5-6-7-8 показали точно такое же поведение.Недвижимость упорядочена.Удаленное свойство сохраняет свою позицию.

Но поскольку это нестандартное поведение, оно может порвать с IE9 или следующей версией любого браузера ...

И, возможно, я что-то пропустил, но чтоточка?Сохранение некоторых символов по сравнению с более надежным кодом, который хорошо работает со сторонней рекламой, системами отслеживания, виджетами и т. Д .?

Не говоря уже о поддержке мобильных браузеров и настольных с небольшой долей рынка.

3 голосов
/ 12 июля 2010

Существует больше браузеров, чем упомянуто здесь: есть другие текущие и будущие браузеры.Ни один из них не обязан реализовывать какое-либо упорядочение при переборе свойств объекта, и не будет долгое время, так как последний ECMAScript 5 не указывает упорядочения.Действительно, команда разработчиков Chrome отказывается менять свою реализацию , несмотря на голосовые запросы, чтобы привести его в соответствие с другими браузерами.Лучший;Как уже отмечалось, не все современные браузеры ведут себя одинаково, и будущие браузеры могут решить не соответствовать вашим предположениям и имеют полное право на это.Поэтому я настоятельно рекомендую не полагаться на какой-либо конкретный порядок в вашем коде.

1 голос
/ 26 июня 2010

Выполнение теста на IE8 на WinXP pro SP2 подтверждает статью MDC. IE8 выполняет итерации членов в порядке их объявления; если существующее свойство удаляется, а затем переназначается, сохраняется его исходное положение итерации. Другие браузеры (я проверял Chrome 5 и Firefox 3) размещают переназначенное свойство в конце порядка итерации.

...