7.6. Обход элементов массива

We use cookies. Read the Privacy and Cookie Policy

Наиболее часто для обхода элементов массива используется цикл for (раздел 5.5.3):

var keys = Object.keys(o); // Получить массив имен свойств объекта о

var values = [] // Массив для сохранения значений свойств

for(var і = 0; і < keys.length; i++) { // Для каждого элемента в массиве

  var key = keys[і]; // Получить имя свойства по индексу

  values[i] = о[key]; // Сохранить значение в массиве values

}

Во вложенных циклах и в других контекстах, когда скорость работы имеет критическое значение, иногда можно увидеть такой оптимизированный способ выполнения итераций по массиву, когда длина массива определяется только один раз, а не в каждой итерации:

for(var і = 0, len = keys.length; і < len; i++) {

  // тело цикла осталось без изменений

}

В примерах выше предполагается, что выполняется обход плотного массива и все элементы содержат допустимые значения. В противном случае необходимо организовать проверку значений элементов массива перед их использованием. Если желательно исключить из обработки значения null, undefined и несуществующие элементы, проверку можно записать так:

for(var і = 0; і < a.length; i++) {

if (!a[і]) continue; // Пропустить null, undefined и несуществ. элементы // тело цикла

}

Если необходимо пропустить только значение undefined и несуществующие элементы, проверку можно записать так:

for(var і = 0; і < a.length; i++) {

if (a[і] === undefined) continue; // Пропустить undefined + несуществ. эл.

  // тело цикла

}

Наконец, если необходимо пропустить только несуществующие элементы, а элементы со значением undefined обрабатывать как обычные элементы, проверку можно записать так:

for(var і = 0; і < a.length; i++) {

if (!(i in a)) continue ; // Пропустить несуществующие элементы

  // тело цикла

}

Для обхода разреженных массивов можно также использовать цикл for/in (раздел 5.5.4). Этот цикл присваивает имена перечислимых свойств (включая индексы массива) переменной цикла. Отсутствующие индексы в итерациях не участвуют:

for(var index in sparseArray) {

  var value = sparseArray[index];

  // Далее следуют операции с индексами и значениями

}

Как отмечалось в разделе 6.5, цикл for/in может возвращать имена унаследованных свойств, такие как имена методов, добавленных в Array.prototype. По этой причине не следует использовать цикл for/in для обхода массивов, не предусмотрев дополнительной проверки для фильтрации нежелательных свойств. Для этого можно было бы использовать, например, такие проверки:

for(var і in а) {

  if (!a.hasOwnProperty(i)) continue; // Пропустить унаследованные свойства

  // тело цикла

}

for(var і in а) {

  // Пропустить і, если оно не является целым неотрицательным числом

  if (String(Math.floor(Math.abs(Number(i)))) !== і) continue;

}

Спецификация ECM AScript допускает возможность обхода свойств объекта в цикле for/in в любом порядке. Обычно реализации обеспечивают обход индексов массивов в порядке возрастания, но это не гарантируется. В частности, если массив имеет и свойства объекта, и элементы массива, имена свойств могут возвращаться в порядке их создания, а не в порядке возрастания числовых значений. Разные реализации по-разному обрабатывают эту ситуацию, поэтому, если для вашего алгоритма порядок выполнения итераций имеет значение, вместо цикла for/in лучше использовать обычный цикл for.

Стандарт ECMAScript 5 определяет множество новых методов, позволяющих выполнять итерации по элементам массивов в порядке возрастания индексов и передавать их функции, определяемой пользователем. Наиболее типичным представителем этих методов является метод forEach():

var data = [1,2,3,4,5]; // Этот массив требуется обойти

var sumOfSquares =0; // Требуется вычислить сумму квадратов элементов

data.forEach(function(x){ // Передать каждый элемент этой функции

   sumOfSquares += х*х; // прибавить квадрат к сумме

});

sumOfSquares // =>55 : 1+4+9+16+25

forEach() и другие родственные методы, предназначенные для выполнения итераций, позволяют использовать при работе с массивами простой и мощный стиль функционального программирования. Они описываются в разделе 7.9, и еще раз мы вернемся к ним в разделе 8.8, когда будем рассматривать приемы функционального программирования.