9.8 KiB
Массив: перебирающие методы
Современный стандарт JavaScript предоставляет много методов для "умного" перебора массивов, которые есть в современных браузерах...
...Ну а для их поддержки в IE8- просто подключите библиотеку ES5-shim. [cut]
forEach
Метод "arr.forEach(callback[, thisArg])" используется для перебора массива.
Он позволяет перебрать массив при помощи функции callback
, что зачастую гораздо элегантнее, нежели цикл for
.
Функция callback
вызывается для каждого элемента с тремя параметрами callback(item, i, arr)
:
- `item` -- очередной элемент массива.
- `i` -- его номер.
- `arr` -- массив, который перебирается.
Например:
//+ run
var arr = ["Яблоко", "Апельсин", "Груша"];
function show(item, i, arr) {
alert(i + ": " + item + " (массив:" + arr + ")");
}
arr.forEach(show);
Второй, необязательный аргумент forEach
позволяет указать контекст this
для callback
. Мы обсудим его в деталях чуть позже, сейчас он нам не важен.
Метод forEach
ничего не возвращает, его используют только для перебора.
filter
Метод "arr.filter(callback[, thisArg])" используется для фильтрации массива через функцию.
Он создаёт новый массив, в который войдут только те элементы arr
, для которых вызов callback(item, i, arr)
возвратит true
.
Например:
//+ run
var arr = [1, -1, 2, -2, 3];
function isPositive(number) {
return number > 0;
}
*!*
var positiveArr = arr.filter(isPositive);
*/!*
alert(positiveArr); // 1,2,3
map
Метод "arr.map(callback[, thisArg])" используется для трансформации массива.
Он создаёт новый массив, который будет состоять из результатов вызова callback(item, i, arr)
для каждого элемента arr
.
Например:
//+ run
var arr = [1, 2, 3, 4];
function square(number) {
return number * number;
}
*!*
var squaredArr = arr.map(square);
*/!*
alert(squaredArr); // получили массив квадратов чисел: 1, 4, 9, 16
every/some
Эти методы используется для проверки массива.
Метод "arr.every(callback[, thisArg])" возвращает true
, если вызов callback
вернёт true
для каждого элемента arr
.
Метод "arr.some(callback[, thisArg])" возвращает true
, если вызов callback
вернёт true
для какого-нибудь элемента arr
.
//+ run
var arr = [1, -1, 2, -2, 3];
function isPositive(number) {
return number > 0;
}
*!*
alert( arr.every(isPositive) ); // false, не все положительные
alert( arr.some(isPositive) ); // true, есть хоть одно положительное
*/!*
reduce/reduceRight
Метод "arr.reduce(callback[, initialValue])" используется для последовательной обработки каждого элемента массива с сохранением промежуточного результата.
Это один из самых сложных методов для работы с массивами. Но его стоит освоить, потому что временами с его помощью можно в несколько строк решить задачу, которая иначе потребовала бы в разы больше места и времени.
Метод reduce
используется для вычисления на основе массива какого-либо единого значения, иначе говорят "для свёртки массива". Чуть далее мы разберём пример для вычисления суммы.
Он применяет функцию callback
по очереди к каждому элементу массива слева направо, сохраняя при этом промежуточный результат.
Аргументы функции callback(previousValue, currentItem, index, arr)
:
- `previousValue` -- последний результат вызова функции, он же "промежуточный результат". Значение `previousValue` при первом вызове равно `initialValue` (второй аргумент `reduce`) или, если у `reduce` нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.
- `currentItem` -- текущий элемент массива, элементы перебираются по очереди слева-направо.
- `index` -- номер текущего элемента.
- `arr` -- обрабатываемый массив.
Разберём работу метода reduce
на примере.
Пусть мы хотим вычислить сумму всех элементов массива. Можно сделать это при помощи цикла, но это как раз подходящий повод познакомиться с reduce
.
Вот решение в одну строку:
//+ run
var arr = [1, 2, 3, 4, 5]
var result = arr.reduce(function(prev, current) { return prev + current }, 0);
alert(result); // 15
Разберём, что в нём происходит.
Здесь начальное значение, с которого начинаются вычисления, равно нулю (второй аргумент reduce
).
Сначала анонимная функция вызывается с этим начальным значением и первым элементом массива, результат запоминается и передаётся в следующий вызов, уже со вторым аргументом массива, затем новое значение участвует в вычислениях с третьим аргументом и так далее.
Таблица вычислений получается такая:
`prev` | `current` | результат | |
---|---|---|---|
первый вызов | `0` | `1` | `1` |
второй вызов | `1` | `2` | `3` |
третий вызов | `3` | `3` | `6` |
четвёртый вызов | `6` | `4` | `10` |
пятый вызов | `10` | `5` | `15` |
Функция-аргумент reduce
могла бы также использовать параметры i
и array
, но здесь в них нет нужды.
Можно сделать ещё короче!
Посмотрим, что будет, если не указать initialValue
в вызове arr.reduce
:
//+ run
var arr = [1, 2, 3, 4, 5]
// убрали 0 в конце
var result = arr.reduce(function(prev, current) { return prev + current });
alert(result); // 15
Результат -- точно такой же! Это потому, что при отсутствии initialValue
в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.
Таблица вычислений будет такая же, за вычетом первой строки.
Метод arr.reduceRight работает аналогично, но идёт по массиву справа-налево:
Итого
Мы рассмотрели методы:
- `forEach` -- для *перебора* массива.
- `filter` -- для *фильтрации* массива.
- `every/some` -- для *проверки* массива.
- `map` -- для *трансформации* массива в массив.
- `reduce/reduceRight` -- для *прохода по массиву с вычислением значения*.
Во многих ситуациях их использование позволяет написать код короче и понятнее, чем обычный перебор через for
.