Особенности использования цикла for—in для обработки массивов

В общем нет существенной разницы в том, при помощи какого цикла просматривается массив: for или for—in. Учитывая, что синтаксис цикла for—in несколько изящнее, чем цикла for, многие кодеры предпочитают использовать первый. Ничего плохого в такой практике нет. Однако цикл for—in — это достаточно тонкий инструмент, и его применение для обработки массивов может сопровождаться разного рода неожиданностями. Приведем несколько примеров.

Представьте, что вам необходимо присвоить некоторое значение всем элементам массива. Если вы примените для этой цели цикл for. то инициализированы будут даже те элементы, которые до этого просто не существовали. Это связано с тем, что цикл for просто последовательно обратится ко всем элементам массива с индексами от 0 до length-1. Если какой-то из элементов не существовал, то использование по отношению к нему оператора присваивания заставит интерпретатор его создать. Совершенно противоположную картину мы будем наблюдать при применении цикла for—in.

Так как данный цикл перечисляет только реально существующие свойства объектов, то элементам, которые не были явно инициализированы ранее (или были удалены оператором delete), не будет присвоено нужного значения:

// Обрабатываем массив при помощи цикла for
var arr:Array = [1, 2, 3]; // Создаем массив из трех элементов
arr.length = 5; // Увеличиваем длину массива до 5 - появляются два
// несуществующих элемента
for (var i = 0; i arr[i] = 0;
trace(arr); // Выводит: 0, 0, 0, 0, 0 (все элементы были инициализированы)
// Обрабатываем массив при помощи цикла for—in
var arr1:Array = [1, 2, 3];
arrl.length = 5;
for (var j in arr1) (
arr1[j] = 0;
trace(arr1); // Выводит: 0, 0, 0, undefined, undefined (инициализированы
// были только реально существующие элементы)

Свойства объектов никак не упорядочиваются.


Это означает, что если элементы массива добашмлись не последовательно, то в его внутреннем представлении они будут организованы не по принципу возрастания индексов, а в том порядке, в котором создавались. Первым будет расположен элемент, созданный последним, а введенный первым элемент будет замыкать список. Отсутствие упорядочивания означает, что выводить индексы элементов массива цикл for—in может в достаточно хаотичном порядке:

var arr:Array = [1, 2, 3];
arr[5] = 5;
arr[4] = 4;
for (var i in arr) {
trace (i); // Выводит: 4 5 2 1 0
}

Менее очевидная, чем описанная выше, сложность при применении цикла for—in для обработки массивов заключается в следующем. Использование методов класса Array может изменить последовательность свойств во внутренней структуре массива. Это никак не скажется на работе цикла for: на первой итерации он обратится к свойству с именем «0», на второй — с именем «1»ит.д.

Цикл for— in же перечисляет свойства объекта в той последовательности, в которой они реально «записаны». Это означает, что первым может быть выведен не элемент с индексом 0, а, например, с индексом 5. Естественно, что это собьет работу большинства алгоритмов.

Для примера трассируем элементы массива, инвертированного методом reverse(), при помощи циклов for и for—in:

var arr:Array = ["арбуз", "дыня", "тыква"];
arr.reverse();
for (var i = 0; i trace(arr[i]); // Выводит: тыква дыня арбуз
}
for (var j in arr) {
trace(j); // Выводит: 2 0 1 (в такой последовательности
// расположены свойства)
trace(arr{j]); // Выводит: арбуз тыква дыня (в массиве элементы
// расположены в совершенно другой последовательности)
}

Можно привести еше немало примеров тех неприятных сюрпризов, которые могут возникнуть при использовании цикла for—in для просмотра элементов массива.


Чтобы не испытать их коварство на себе, автор советует вам воздержаться от применения for—in там, где с успехом можно обойтись пусть не таким изящным, зато простым и надежным циклом for..



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Action Script на эту тему:
Выделение фрагмента массива
Длина массива. Свойство length
Добавление элементов в массив
Извлечение и переопределение элементов массива
Инверсия массива

Вернуться в раздел: Action Script / 7. Массивы (класс Array)