Обрабатывает ли JavaScript array.forEach элементы в порядке возрастания
В JavaScript у меня может быть массив с отверстиями:
a = [];
a[0] = 100;
a[5] = 200;
a[3] = 300;
a.forEach(function(x) {alert(x);});
Я не смог найти информацию о том, будут ли элементы обрабатываться в порядке возрастания, или это ненадежный факт.
Я проверил, что цикл "for.. in" пересекает индексы массива в порядке возрастания, в то время как имена свойств объекта просматриваются в том же порядке, в котором они были добавлены к объекту (по крайней мере, это выглядит так).
(Т.е. похоже, что массивы внутренне являются деревьями некоторого вида, а объекты являются хеш-таблицами.)
Я только что обнаружил, что Rhino JavaScript также пересекает несуществующие элементы: http://ideone.com/7Z3AFh (в отличие от forin).
Ответы
Ответ 1
В спецификации ECMA-262, 5th edition и MDN Array.forEach()
страница показаны алгоритм для .forEach()
, и он будет определенно перебирать элементы массива в порядке возрастания индекса (пропуская индексы, которым никогда не присваивалось значение).
Конечно, некоторые браузеры могут не реализовывать этот алгоритм правильно, но я не знаю никого из них.
Ответ 2
В спецификации указано, что forEach
будет посещать элементы массива в числовом порядке. Он не посещает элементы, которые не существуют. Подробнее см. Ссылку. Итак, для вашего массива примеров он будет посещать элемент 0
, затем 3
, затем 5
. Порядок, в котором вы добавляете их в массив, не влияет на порядок, в котором они были посещены.
Я проверил, что цикл "for.. in" обходит индексы массива в порядке возрастания, тогда как имена свойств объекта пересекаются в том же порядке, в котором они были добавлены к объекту (по крайней мере, это выглядит так).
Порядок, в котором for-in
посещает свойства объекта, не, определенный спецификацией, даже в ES2015 (ака ES6), несмотря на то, что ES2015 определяет порядок для свойств объекта — этот порядок не применяется к for-in
или Object.keys
. (Подробнее об этом в этом ответе.) Если вы хотите посетить свойства в порядке, определенном в ES2015, вы можете использовать Object.getOwnPropertyNames
(для свойств, которые не определены с именами Symbol
) или Reflect.ownKeys
(как для Symbol
, так и для строковых имен свойств [помните, что имена числовых свойств действительно являются строками]). Оба они уважают порядок собственности.
Ответ 3
Прямо из стандарта ECMAScript
forEach вызывает callbackfn один раз для каждого элемента, присутствующего в массиве, в порядке возрастания. callbackfn вызывается только для элементов массив, который фактически существует; он не называется отсутствующими элементами массив.
Итак, Array.forEach пропустит некоторые элементы в массиве. Ваш пример
a.forEach( function( value ) { console.log( value ) }); // prints 100, 300, 200
Если вы хотите пересечь массив в порядке возрастания, и все ваши элементы являются числами, вы можете отсортировать массив заранее так
a.sort( function( a, b ) { return a - b });
// this now prints 100, 200, 300
a.forEach( function( value ) { console.log( value ) });