Перебор элементов


Как не надо перебирать элементы Перед тем, как рассказать, как следует перебирать элементы массивов, стоит сказать, как их не следует перебирать. Уж слишком распространён перебор элементов с помощью цикла for-in. var a = [0, 1, 2, 3, 4, 5, 6], props = ''; for (var i in a) { props += i; } alert(props); // В большинстве случаев 0123456 Чем же так плох for-in для перебора элементов массива? Тем, что он перебирает все свойства объекта, не имеющие атрибута DontEnum. Из этого следуют как минимум 2 проблемы. Во-первых, свойства не обязаны быть как-либо отсортированными, т.е. спецификация языка не обещает, что в данном случае элементы будут перебраны по порядку от 0 до length - 1. Хотя на данный момент все JS-движки сортируют свойства массивов, а некоторые версии браузеров сортируют даже числовые свойства у обычных объектов. Поэтому данная проблема не очень актуальна. Во-вторых, как уже было сказано, в таком случае перебираются все свойства массива, а не только числовые индексы. Обычно в таких случаях говорят, что не надо засорять Array.prototype собственными методами, но даже без этого могут возникнуть проблемы. Возьмём, к примеру, массив, возвращаемый строковым методом match. var a = 'ab'.match(/((a)(b))/), props = ''; for (var i in a) { props += i + ' '; } alert(props); // IE: input index lastIndex 0 1 2 3 // Остальные браузеры: 0 1 2 3 index input Т.е. стандартный метод строки возвращает массив, в котором помимо числовых индексов имеется несколько других свойств. Поэтому, если перебирать такой массив с помощью for-in, мы получим не только числовые индексы. Как перебирать элементы массивов Минимально возможный индекс в массиве — 0, максимально возможный — length - 1, поэтому для того, чтобы перебрать все элементы массива, нужно перебрать числа от 0 до length - 1 включительно. А для этого существует цикл for. var a = [0, 1, 2, 3, 4, 5], sum = 0; for (var i = 0; i < a.length; i++) { sum += a[i]; } alert(sum); // 15 Если в массиве нет пропусков, т.е. в большинстве случаев, то такого цикла вполне достаточно. Однако если перебирается разреженный массив, то нужно проверять, существует ли элемент с текущим индексом. var a = [1, 2, , , 3, , 5]; var props = ''; for (var i = 0; i < a.length; i++) { props += a[i] + ' '; } alert(props); // 1 2 undefined undefined 3 undefined 5 // Перебрали и несуществующие элементы props = ''; for (var i = 0; i < a.length; i++) { if (i in a) { props += a[i] + ' '; } } alert(props); // 1 2 3 5 // Перебрали только существующие элементы // Не забываем, что undefined обманчиво a[2] = undefined; props = ''; for (var i = 0; i < a.length; i++) { if (i in a) { props += a[i] + ' '; } } alert(props); // 1 2 undefined 3 5 Наиболее правильной конструкцией для перебора элементов массива является for (var i = 0, length = a.length; i < length; i++) { if (i in a) { // делаем что-то с элементом массива. } } А чтобы не писать такие конструкции, лучше воспользоваться методом forEach a.forEach(function(element, index) { // делаем что-то с элементом element, у которого индекс index });