Содержание

JavaScript Array.forEach() В реальном мире

const products = ['бобы', 'пицца', 'курица', 'лосось'] // Выводим в консоль каждый элемент массива products.forEach(продукт => console.log(продукт)) // бобы // пицца // курица // salmon

В этой серии статей « итерация JavaScript в реальном мире » я хочу поделиться с вами некоторыми из наиболее распространенных методов итерации JavaScript, используя примеры, которые максимально похожи на то, как выглядит их использование в реальный мир. Я постараюсь избегать `foo` и `bar` или слишком сложных примеров. Боюсь, не будет много упоминаний о ваших питомцах и друзьях. Вместо этого мы подробно рассмотрим, как работает этот метод, зачем он нам нужен и как он будет выглядеть в типичном современном интерфейсном коде.

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

forEach()

Так что же такое метод Array.forEach() ? По сути, это очень простой метод. Он делает только одну вещь, но делает это очень хорошо. Он выполнит функцию, которую мы предоставляем для каждого элемента массива, который мы хотим повторить.

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

Если вы читали предыдущую статью из серии о map() , вы справедливо подумали, что это звучит подозрительно одинаково. И в чем-то ты будешь прав. Но между ними есть одно фундаментальное различие, и в этом различии заключается решение о том, что использовать.

Позвольте мне вернуться к примеру, который мы использовали в предыдущей статье:

const products = ['бобы', 'пицца', 'курица', 'лосось'] products.map((продукт, индекс) => console. log(продукт, индекс)) // 'бобы', 0 // 'пицца', 1 // 'курица', 2 // 'salmon', 3

Я использовал этот пример, чтобы показать, как map() дает нам индекс элемента в массиве. Но, удалив индексную часть, он выглядит точно так же, как наш первый forEach() 9пример 0004. Итак, что происходит? Что ж, правда в том, что этот пример

map() — это антишаблон, который не следует использовать. Я использовал его только для иллюстрации одного момента. forEach() — это то, что мы всегда должны были использовать для чего-то подобного.

Причина кроется в том, что map() на каждой итерации возвращает новый элемент и помещает его в новый массив. Поэтому, когда цикл завершается , map() возвращает нам совершенно новый массив с результатами итерации. Тогда как forEach() этого не делает. Он просто выполняет функцию. Поэтому вы должны спросить себя, нужен ли вам возвращаемый массив. Если вы не собираетесь использовать результирующий новый массив из операции

map() , как в приведенном выше примере, где вы только регистрируете элементы, вам не следует использовать map() . Вот где мы используем forEach() вместо .

Давайте подчеркнем этот момент, потому что это ключ к пониманию того, когда использовать каждый из них. карта() возвращает массив, forEach() — нет. Если вы используете возвращенный массив позже в своем коде, используйте map() , в противном случае forEach() — ваш друг.

Теперь, когда мы установили, что представляет собой этот метод, а что нет, мы готовы отправиться в наш интернет-магазин, чтобы посмотреть, как мы можем применить

forEach() в реальном мире.

В реальном мире

Как и в предыдущих статьях, мы продолжим работу с реалистичным контекстом, на котором будем основывать наши примеры. Мы работаем над кодовой базой интернет-магазина. Это простое приложение, которое я создал специально для демонстрации наших примеров в действии. Вы можете ознакомиться с веб-приложение и см. forEach() , используемое напрямую, и вы можете увидеть код в его репозитории GitHub . Но сначала мы пройдемся по всему здесь.

Итак, давайте начнем исследовать реалистичный контекст, где forEach() может пригодиться. Сначала это немного сложно, потому что до сих пор во всех наших предыдущих методах мы всегда брали исходный набор товаров, выставленных в магазине, а затем что-то делали с ними и показывали результат на экране. Но, как мы узнали, forEach()   не возвращает массив и не используется для этого.

Сначала мы начнем с простого примера регистрации. Давайте немного пофантазируем, чем скромный console.log() . Что произойдет, если мы сделаем это с каждым из наших объектов продукта в магазине?

products.forEach(product => console.table(product))

Результат будет выглядеть так в нашей консоли [открыть консоль с помощью Command + Option + J (Mac) или Control + Shift + J (Windows, Linux, Chrome OS).

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

Отлично, это мило и все такое, но кроме разработки, это бесполезно в нашем готовом к производству интернет-магазине.

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

Я не хочу тратить много времени на Window.localStorage , вы можете прочитать больше об этом здесь , но в двух словах, наш объект окна предоставляет нам метод для хранения некоторых данных в нашем пользовательском браузер, который сохраняется даже после перезагрузки или закрытия и повторного открытия страницы. Мы можем хранить данные там, а затем читать их снова, когда нам это нужно. Пример использования для этого — хранить там, показывали ли вы пользователю всплывающее модальное окно с просьбой подписаться на информационный бюллетень, когда они посещают ваш сайт. Таким образом, вы можете гарантировать, что пользователь увидит его только один раз.

Если вы откроете свои инструменты разработчика, я использую Chrome на изображении ниже, вы найдете вкладку под названием «Приложение». На левой панели вы можете открыть вкладку «Локальное хранилище» и выбрать текущий URL-адрес. Вы увидите таблицу ключ/значение, где мы можем сохранить или прочитать данные.

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

Предположим, что цены в нашем магазине регулярно колеблются в зависимости от рыночных цен. И эти цены сохраняются в нашей базе данных, откуда мы получаем список продуктов для отображения на экране. Нам нужна функция, которая показывает пользователю значок на продукте, если его цена упала по сравнению с последним разом, когда он его видел. Мы не знаем, что пользователь видел во время последнего посещения. Таким образом, мы можем сохранять в локальном хранилище нашего пользователя цену каждого продукта на экране каждый раз, когда они посещают страницу. Таким образом, прежде чем отображать новые цены, мы можем провести сравнение с ценой, сохраненной в локальном хранилище, и, если новая цена ниже, мы можем отобразить значок «Снижение цены» на этом продукте.

Для целей нашего примера нам действительно не нужно ничего из этого разрабатывать. Единственная часть, которая нас интересует, — сохранить цену каждого продукта в локальном хранилище и посмотреть, насколько forEach() идеально подходит для этого. Остальное — показать реальное использование этого метода.

products.forEach((product) => localStorage.setItem(product.name, product.price)

Как видите, мы начинаем с массива товаров. Применяем forEach() и передайте методу функцию обратного вызова для выполнения на каждой итерации. Функция принимает текущий выбранный элемент массива в качестве первого аргумента, который мы называем «продукт».

Затем мы выполняем нужную нам функцию. В этом случае мы используем API `localStorage`, который позволяет нам сохранять запись, используя собственный метод setItem() . Не слишком беспокоясь об этой части, мы просто передаем ей первый аргумент, который будет ключом в таблице локального хранилища, и второй аргумент, который будет значением. В этом случае мы сохраним название товара в качестве ключа, а цену в качестве значения. Если это работает правильно, он должен сохранить каждый продукт и его цену в нашем локальном хранилище. И вот как это будет выглядеть:

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

Более того

Точно так же, как мы видели с предыдущими рассмотренными методами массива, этот также предоставляет нам три аргумента, которые мы можем использовать. Первый — это текущий выбранный элемент из массива, который мы уже видели в примере выше. Два других - индекс и массив .

myArray.forEach((element, index, array) => // Делаем вещи)

Индекс — это позиция текущего выбранного элемента в массиве, а последний аргумент — это сам исходный массив, который мы итерируем на.

Мы назвали здесь второй аргумент «индекс», а третий аргумент «массив». Но, как и `элемент`, это также имена переменных. Вы можете назвать их как хотите. Вы можете называть их «солнце» и «джиндо», и ничего не изменится. Помните, что здесь важно не имя, а позиция аргумента. Первым всегда является элемент, вторым — всегда индекс, а третьим — массив, с которого мы начали. Тем не менее, несмотря на вашу малоизвестную отсылку к поп-культуре, мы склонны называть вещи так, чтобы их было легче читать. Таким образом, второй аргумент почти всегда называется «индекс» или «i» по соглашению, а третий обычно — «массив» или «арр».

Что делать, если нам нужно, чтобы наша функция обратного вызова имела несколько строк? Затем мы просто добавляем фигурные скобки.

products.forEach(product => { const предыдущая цена = localStorage.getItem(product.name) если (предыдущая цена !== product.price) { localStorage.setItem(product.name, product.price) } })

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

Как это выглядело до ES6

В ES6 у нас есть стрелочные функции и много замечательных вещей, которые делают наш код более читабельным. Но важно знать, как все выглядело раньше, потому что вы столкнетесь с этим способом написания в куче старых кодовых баз, которые все еще используются, и вы встретите его в старых примерах на Stack Overflow и тому подобное. Вот как мы написали это до ES6:

products.forEach(function(product) { console.table(продукт) })

Как видите, до того, как мы получили функцию стрелки, нам нужно было ключевое слово function , стрелка исчезла, и нам нужны фигурные скобки.

Нам не нужно ключевое слово return , потому что, как мы уже видели, forEach() не помещает результат в новый массив.

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

Нам не нужно этого делать, но если бы мы написали цикл for вместо forEach() , это выглядело бы так.

функция logTable(продукты) { for(пусть i = 0; i < products.length; i++) { console.table(продукт) } }

Таким образом, реализация forEach() под капотом довольно прозрачна.

// обратный вызов — это функция, которую мы создаем и передаем в forEach Array.prototype.forEach = функция (обратный вызов) { // ‘this’ относится к массиву for (пусть я = 0; я < this. length; я ++) { // вы можете увидеть три аргумента, которые получает наша функция обратного вызова обратный вызов (это [я], я, это) } }

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

forEach() — гораздо более короткая, лаконичная и читабельная реализация.

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

Как всегда, лучший способ научиться пользоваться им — много практиковаться.

Откройте консоль и попробуйте некоторые из этих примеров или даже разветвите проект GitHub примера и попробуйте изменить что-то и сохранить, например, другие свойства продукта в локальном хранилище. И если вы застряли или у вас есть какие-либо вопросы, я всегда рад помочь, вы можете найти меня в Твиттере для всего dev

Полезности для начинающих: Является ли JavaScript Array.forEach асинхронным? | Леланд Зак

Полезности для начинающих: является ли JavaScript Array.forEach асинхронным? | Леланд Зак | Medium

2 мин чтения

·

21 августа 2019 г.

Циклы JavaScript выполняются асинхронно?

Если вы когда-либо пытались выполнить какую-либо операцию в цикле JavaScript, которая приводила к неупорядоченным результатам, вот почему.

Является ли Array.forEach асинхронным?

Это не асинхронно. Это блокирует. Те, кто впервые изучил такие языки, как Java, C или Python, прежде чем попробовать JS, запутаются, когда попытаются поставить произвольную задержку…

Автор: Леланд Зак

121 Подписчик

Учимся программировать и обучаю этому на ходу

Еще от Леланда Зака ​​

Лиланд Зак

в

Создайте простого чат-бота с помощью Python и Google Search

Создайте ChatBot API с нуля с помощью Python 3.

Машинное обучение не требуется.

·5 min read·1 сентября 2019 г.

Леланд Зак

Полезности для начинающих: JavaScript Async и Await in Loops

Примеры циклов JavaScript, которые правильно используют шаблон async/await. Выполнять асинхронные операции из тела цикла.

· 2 мин. Читать · сентябрь 2, 2019

Leland Zach

DART Изолят 2-й проезд

Узнайте, как использовать язык программирования DART, чтобы создать асинхронные нити с классом изолята.

·Чтение через 2 минуты·6 августа 2019 г.

Леланд Зак

Полезности для начинающих: преобразование объекта JavaScript в строку JSON

Новичок, ванильные примеры кода JavaScript для кодирования и декодирования объектов JS в строки JSON и из них.

·2 минуты чтения·29 июля 2019 г.

Просмотреть все от Leland Zach

Рекомендовано Medium

Мелих Юмак

в

Nodejs Developer Дорожная карта 2023

Ознакомьтесь с дорожной картой для разработчиков nodejs на 2023 год. A пошаговое руководство о том, как стать разработчиком nodejs, повысить уровень знаний в качестве разработчика nodejs

·7 минут чтения·29 января

Андреас Суджоно

10 самых каверзных вопросов по Javascript, которые часто задают интервьюеры

10 самых каверзных вопросов по Javascript, которые часто задают интервьюеры. Убедитесь, что вы знаете их все!

·8 мин чтения·17 декабря 2022 г.

Списки

Истории, которые помогут вам расти как разработчику программного обеспечения

19 историй·29 сохранений

Выбор персонала

30 4 этажа·66 сохранений

Реми Виллюлль

in

Кэширование с помощью Redis и Node.