Вы здесь: Главная » JavaScript » Замена методов массива forEach(), map(), filter(), reduce() с помощью цикла for

Замена методов массива forEach(), map(), filter(), reduce() с помощью цикла for

Такие методы массивов, как forEach(), map(), filter(), reduce() появились еще в спецификации ES5, так что на данный момент они прочно вошли в стандартный набор средств JavaScript-программиста. Однако на первоначальном этапе эти методы временами вызывают недопонимание. Непонятным в них является, как правило, механизм работы callback-функции, которая запускается в каждом методе, причем с некоторыми отличиями. Давайте разберемся на примере цикла for(), как работает функция-коллбек.

Метод forEach()

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

Как правило, метод array.forEach() используется для перебора элементов массива с целью вывода какой-либо информации. Например, у нас есть массив строк с именами и фамилиями студентов, и нам нужно вывести их в виде нумерованного списка.

Пример в действии:

Что можно понять из кода выше? Внутри метода forEach() запускается либо обычная, либо стрелочная функция с одним аргументом oneStudent, который при каждом вызове этого метода указывает на очередного студента из массива students, то есть в переменной oneStudent находится значение каждого элемента массива students. Как происходит вызов функции? Примерно так же, как и внутри цикла for() ниже, но в цикле переменная oneStudent заменена на i-тый элемент массива students, что выглядит в коде, как  students[i]:

Давайте посмотрим на результат работы цикла for и сравним 2 примера:

Как можно заметить, списки ничем не отличаются, т.к. механизм работы подобен.

Метод forEach() с двумя аргументами

Поскольку метод forEach() подразумевает, что в него можно передать от одного до трёх аргументов (элемент массива, индекс элемента массива и сам массив), то мы можем  воспользоваться не одним, а двумя аргументами, чтобы увидеть, что и в этом случае способы похожи.

В коде выше мы видим тот же синтаксис, что и в цикле for() для обращения к каждому элементу массива (students [i] ). Хотя, на мой взгляд, использование переменой oneStudent для доступа к значению элемента массива намного удобней.

Ниже вы увидите результат работы кода.

Используем для замены метода forEach() цикл for..of

Ещё один способ, пожалуй, даже более похожий на запись функции-колбека в методе forEach() дает нам цикл for...of:

В этом примере в синтаксисе цикла используется такая же переменная oneStudent, как и в методе forEach(). В обоих случаях это не что иное, как способ добраться к значению каждого элемента массива, но в методе forEach() это происходит при вызове функции-коллбека для каждого элемента массива, а в цикле for...of - при каждой итерации цикла.

И ещё один результат:

И здесь мы видим, что список сформирован точно так же.

Все 4 варианта перебора массива для вывода его элементов в виде списка представлены в примере ниже. Сравните ещё раз, если есть необходимость.

See the Pen
for for..of vs array.forEach()
by Elen (@ambassador)
on CodePen.0

Важное замечание: метод forEach() ничего не возвращает (точнее возвращает  undefined) в отличие от методов map()  и filter(), которые возвращают новый массив на основе исходного, и метода reduce(), который возвращает одно значение, сформированное на основе обхода всех элементов массива.

Метод map()

Наименование метода map() переводится, как "карта" с английского языка. С его помощью выполняется обход всех элементов массива с целью их изменения, и формируется новый массив из измененных элементов. То есть после использования метода map() мы получаем новый массив с новыми значениями на основе значений элементов исходного массива, но при этом исходный массив не изменяется.

Из кода видно, что, во-первых, используется оператор return для помещения каждого нового элемента в новый массив при вызове функции-коллбека, а во-вторых, при вызове метода map() вам нужно объявить какую-то переменную, в которую будет записан новый массив, сформированный на основе исходного. На картинке ниже  в новый массив попадают элементы, увеличенные на 1.

Метод map() для массивовКод примера:

Результат выполнения кода:

Заменяем код метода map() циклом for():

Все достаточно просто + работает корректно + результат такой же, как и с помощью метода map().

Метод filter()

Метод array.filter() предназначен для фильтрации массива по определенному принципу или, точнее, условию. Причём результатом фильтрации является создание нового массива на основе исходного. То есть метод filter() не только фильтрует исходный массив, но и возвращает отфильтрованный массив в качестве значения. Если элемент массива соответствует проверяемому условию, то он попадает в результирующий массив, если же нет, то будет пропущен. Поэтому в методе filter() всегда присутствует условие, которое всегда должно вернуть либо true (и элемент попадет в новый массив), либо false (и этого элемент не будет в новом массиве).

Синтаксис метода filter():

Отсюда можно сделать вывод, что после выполнения фильтрации мы получим меньший массив, чем исходный. Этим метод filter()  отличается от метода map(), в котором в новый массив попадают все элементы исходного, но с предварительным изменением значений.

Метод filter() для массивов

Например, у нас есть некий массив чисел от 1 до 7, который нужно отфильтровать таким образом, чтобы в новый массив попали только те значения, которые больше 5. Код с методом filter():

Результат:

Код для выполнения этой операции с циклом for будет такой:

Давайте посмотрим на результат:

Чаще всего фильтровать приходится не простые массивы, а массивы объектов, так как в них, как правило, содержаться те элементы, которые имеют разные свойства, по которым массивы могут выводится в тело документа. Например, вывод товаров магазина в зависимости от выбора нескольких критериев пользователем. Ниже мы рассмотрим пример фильтрации массива объектов купленных продуктов из общего списка продуктов.

See the Pen filter Array of objects JS by Elen (@ambassador)
on CodePen.0

Метод reduce()

Синтаксис метода:

В отличие от остальных методов array.reduce()собирает (или уменьшает, если использовать перевод англ. слова reduce на русский язык) до одного значения значения всех элементы массива.

Метод reduce() для массивов

Примечание: изображения взяты из статьи  .map(), filter() & .reduce() — animated

Как правило, метод reduce() используют для сложения значений числовых массивов. В примере с картинки у нас есть массив, в котором сумма чисел составляет 1+2+3+4+5+6+7 = 28. Давайте получим это значение с помощью метода reduce() и цикла for().

Проверяем работу метода:

Используем цикл for для замены метода reduce():

Подсчет суммы привел к точно таким же результатам.

Учтите, что в метод reduce() можно передать начальное значение, которое необходимо учитывать в коде. То есть при его отсутствии подсчет начинается с 0-го элемента массива, а при наличии - именно с этого значения:

Проверяем:

Возможности использования метода array.reduce()

Как правило, с помощью метода reduce() рассчитывают сумму или, реже, разность значений элементов числовых массивов. Однако, мы также можем найти минимальное и максимальное число в массиве, используя этот метод:

В коде выше представлены стрелочные функции в качестве коллбеков для работы с массивом. Переменые elem1 и elem2 обозначают сначала нулевой и первый элементы массива, а затем результат выполнения действия и следующий элемент массива.

Пример с использованием методов map() и reduce() для подсчета суммы значений в ячейках таблицы

Используем таблицу с числовыми значениями для подсчета суммы чисел в нескольких ячейках.

В коде выше мы получаем доступ ко всем последним ячейкам таблицы с id="cart"  (переменная lastTd)  и к последней пустой ячейке в tfoot. Затем для того чтобы иметь возможность использовать методы массивов, мы преобразуем коллекцию html-элементов в обычный массив с помощью метода Array.from().

В переменную lastTdValues с помощью метода map() мы помещаем в виде массива значения из последних ячеек, преобразуя их в числа. Затем в последнюю ячейку мы поместим результат сложения всех элементов массива lastTdValues с помощью свойства textContent.

Проверяем, как работает код:

Стоимость товаров по размерам
№ п/п Название Цена, грн
1 Юбка в клетку 400
2 Брюки в полоску 580
3 Симпатичное платье с принтом 390
4 Сумочка с блестками 480
Итого

Неочевидное применение метода reduce(), а также методов map() и filter()

В примере ниже мы используем метод reduce() для формирования html-кода в виде списка или нескольких div-ов. В этом случае мы будем использовать уже не массив чисел, а массив объектов, в котором собрана информация о книгах. Каждый элемент массива сожержит одинаковые свойства, описывающие title - название книги, author - автора книги, cover - ссылку на фото обложки, price - стандартную цену книги, sale - цену по распродаже и inStock - наличие на складе. В коде ниже вы найдете часть объектов, весь список - в примере с codepen.io.

Для того чтобы вывести список книг с помощью метода reduce(), можно использовать такой код:

Здесь мы формируем список из элементов массива arr, передаваемого в функцию printBookList(arr), используя Список объектов при вызове функции для массива объектоввозможность метода array.reduce() формировать на основе всех элементов массива один конечный результат, заданный константой list. Таким результатом станет строка в виде переменной html, в которую мы помещаем начальное значение '<ol>', а затем при каждом вызове функции для каждого элемента массива (переменная elem) добавляем к переменной html строку '<li>' + elem + '</li>', формируя таким образом нумерованный список из всех элементов массива. После обхода в функции всех элементов массива мы завершаем формирования нумерованного списка, добавляя уже к константе list завершающий список тег '</ol>'.

Если мы выведем в окно документа список из наших книг с помощью document.write( printBookList(books) ); то увидим список из объектов, что не очень презентабельно.

Значительно интересней использовать эту функцию для вывода списка элементов для массивов с числовыми или строковыми значениями. Поэтому мы используем метод array.filter() для того, чтобы отфильтровать массивы по определенному признаку, а затем методом array.map() сформировать строку из имени автора и названия книги для нового массива. Все это запишем в виде функции, а затем вызовем эту функцию, чтобы узнать, сколько и какие книги из массива продаются по распродаже (свойство sale не имеет значение null), и какие книги есть на складе (inStock: true):

В коде выше мы используем вывод новых массивов с помощью функции printBookList() и printBookListMin(). Работают они одинаково при несколько разном синтаксисе за счет использования в функции printBookListMin() стрелочной функции-коллбека для метода reduce().

Результатом использования функций в этот раз будут 2 вполне читабельных списка:

Книги по распродаже

  1. Дрисколл Т. Я слежу за тобой
  2. Дойл А. Рассказы о Шерлоке Холмсе
  3. А.Дж. Финн Женщина в окне
  4. Владимирская А. Игра на выживание

Книги в наличии

  1. Фаулз Дж. Коллекционер
  2. Дрисколл Т. Я слежу за тобой
  3. Дойл А. Рассказы о Шерлоке Холмсе
  4. Акунин Б. Планета Вода.
  5. А.Дж. Финн Женщина в окне
  6. Владимирская А. Игра на выживание

Вы можете сравнить список книг, выводимый с помощью метода reduce() списком в html или с помощью метода array.join() с разделителем в виде <br>, расскомментировав строки 11 и 15.

Вывод списка книг с использованием всех свойств

Для того чтобы вывести список книг с названиями, авторами, обложкой, стандартной ценой и ценой распродажи, если таковая имеется, а также с указанием наличия книги на складе, нужно создать функцию, которая бы учитывала все особенности именно этого типа объектов. Для этой цели мы опять воспользуемся методом reduce(), но будем формировать уже не нумерованный список, а несколько div-ов:

Именно с вызова данной функции начинается пример ниже. Он также требует дополнения в виде css-стилей. В нем видно, что те книги, которых нет в наличии, выводятся полупрозрачными и с соответствующей записью после цены.

See the Pen Array map(), filter(), reduce() by Elen (@ambassador) on CodePen.0

Автор: Админ

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *