HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Функции высшего порядка - элегантное решение, которое делает код проще, понятнее и эффективнее. Также при первом знакомстве они - верный источник головной боли, от которой не спасают ни гайды в интернете, ни попытки объяснить происходящее словами "свертка" и "отображение".</p>
1 <p>Функции высшего порядка - элегантное решение, которое делает код проще, понятнее и эффективнее. Также при первом знакомстве они - верный источник головной боли, от которой не спасают ни гайды в интернете, ни попытки объяснить происходящее словами "свертка" и "отображение".</p>
2 <p>Этому весьма способствует сложившаяся традиция демонстрировать логику таких функций абстрактными примерами, в которых суммируются какие-то a и b:</p>
2 <p>Этому весьма способствует сложившаяся традиция демонстрировать логику таких функций абстрактными примерами, в которых суммируются какие-то a и b:</p>
3 <p>Я предлагаю разобрать принцип действия filter, map и reduce на примере, приближенном к жизни и наконец-то разложить все по полочкам.</p>
3 <p>Я предлагаю разобрать принцип действия filter, map и reduce на примере, приближенном к жизни и наконец-то разложить все по полочкам.</p>
4 <h2>Содержание</h2>
4 <h2>Содержание</h2>
5 <ul><li><a>Жизненный пример</a></li>
5 <ul><li><a>Жизненный пример</a></li>
6 <li><a>I. Filter</a></li>
6 <li><a>I. Filter</a></li>
7 <li><a>II. Map</a></li>
7 <li><a>II. Map</a></li>
8 <li><a>III. Reduce</a></li>
8 <li><a>III. Reduce</a></li>
9 <li><a>IV. Бонус - функция forEach и особый синтаксис</a></li>
9 <li><a>IV. Бонус - функция forEach и особый синтаксис</a></li>
10 <li><a>Заключение</a></li>
10 <li><a>Заключение</a></li>
11 </ul><h2>Жизненный пример</h2>
11 </ul><h2>Жизненный пример</h2>
12 <p>Представим, что, отчаявшись разобраться с функциями высшего порядка самостоятельно, вы создаете топик в блоге с приблизительно таким заголовком:</p>
12 <p>Представим, что, отчаявшись разобраться с функциями высшего порядка самостоятельно, вы создаете топик в блоге с приблизительно таким заголовком:</p>
13 <p>'Пробую использовать функции высшего порядка, но ничего не выходит!!!!!'</p>
13 <p>'Пробую использовать функции высшего порядка, но ничего не выходит!!!!!'</p>
14 <p>Видя количество восклицательных знаков в вашем предложении, неравнодушные пользователи бросаются делиться ценными советами. Они пишут комментарии, и, с точки зрения сайта, на котором все происходит (ну ладно, конечно, это Хекслет), комментарии пользователей складываются в один большой массив:</p>
14 <p>Видя количество восклицательных знаков в вашем предложении, неравнодушные пользователи бросаются делиться ценными советами. Они пишут комментарии, и, с точки зрения сайта, на котором все происходит (ну ладно, конечно, это Хекслет), комментарии пользователей складываются в один большой массив:</p>
15 <p>Как видите, массив представлен объектами, каждый из которых описывает один комментарий: кто его написал, какой у этого пользователя рейтинг, что именно написано и так далее (конечно, в реальности все немного сложнее, но для демонстрации работы наших функций этого достаточно).</p>
15 <p>Как видите, массив представлен объектами, каждый из которых описывает один комментарий: кто его написал, какой у этого пользователя рейтинг, что именно написано и так далее (конечно, в реальности все немного сложнее, но для демонстрации работы наших функций этого достаточно).</p>
16 <p>Чтобы эффективно манипулировать таким массивом и использовать данные внутри, нам как раз очень пригодятся filter, map и reduce.</p>
16 <p>Чтобы эффективно манипулировать таким массивом и использовать данные внутри, нам как раз очень пригодятся filter, map и reduce.</p>
17 <h2>I. Filter</h2>
17 <h2>I. Filter</h2>
18 <p>Функция filter самая простая и понятная из великолепной тройки. Она проходится по массиву и отбирает только те элементы, которые подходят под заданное условие. А те, которые не подходят, соответственно, игнорирует.</p>
18 <p>Функция filter самая простая и понятная из великолепной тройки. Она проходится по массиву и отбирает только те элементы, которые подходят под заданное условие. А те, которые не подходят, соответственно, игнорирует.</p>
19 <p>Допустим, мы хотим выбрать из нашей коллекции только те комментарии, в которых упоминается console.log: в конце концов, отладка - это самый важный инструмент для понимания происходящего в коде, наверняка такой совет поступит не единожды.</p>
19 <p>Допустим, мы хотим выбрать из нашей коллекции только те комментарии, в которых упоминается console.log: в конце концов, отладка - это самый важный инструмент для понимания происходящего в коде, наверняка такой совет поступит не единожды.</p>
20 <p>Применим filter:</p>
20 <p>Применим filter:</p>
21 <p>Что здесь произошло? В функцию filter мы передали callback - по большому счету, просто функцию, аргументом которой является наш элемент коллекции - комментарий пользователя.</p>
21 <p>Что здесь произошло? В функцию filter мы передали callback - по большому счету, просто функцию, аргументом которой является наш элемент коллекции - комментарий пользователя.</p>
22 <p>Для каждого элемента коллекции мы выбрали интересующую нас деталь, а именно, текст комментария comment.text, и проверили, содержит ли текст подстроку "console.log". Если это так, callback вернет true, и весь наш объект-комментарий будет добавлен в результат. В противном случае, callback вернет false, и результат не изменится.</p>
22 <p>Для каждого элемента коллекции мы выбрали интересующую нас деталь, а именно, текст комментария comment.text, и проверили, содержит ли текст подстроку "console.log". Если это так, callback вернет true, и весь наш объект-комментарий будет добавлен в результат. В противном случае, callback вернет false, и результат не изменится.</p>
23 <p>Вот, кстати, и он:</p>
23 <p>Вот, кстати, и он:</p>
24 <p>Мы успешно отфильтровали комментарии по условию, дело сделано!</p>
24 <p>Мы успешно отфильтровали комментарии по условию, дело сделано!</p>
25 <p>Рекомендую вам самостоятельно потестировать этот код на repl.it, чтобы убедиться, что все работает именно так. Последуйте совету Ивана Редьюсова - используйте отладку и посмотрите, как добавляются элементы ;)</p>
25 <p>Рекомендую вам самостоятельно потестировать этот код на repl.it, чтобы убедиться, что все работает именно так. Последуйте совету Ивана Редьюсова - используйте отладку и посмотрите, как добавляются элементы ;)</p>
26 <h2>II. Map</h2>
26 <h2>II. Map</h2>
27 <p>Функция map немного сложнее. Для каждого обработанного элемента коллекции она добавит в результат один элемент, измененный так, как мы укажем в callback функции.</p>
27 <p>Функция map немного сложнее. Для каждого обработанного элемента коллекции она добавит в результат один элемент, измененный так, как мы укажем в callback функции.</p>
28 <p>В этом примере мы даже не изменили, а заменили элементы. Функция вернула 5 на каждый элемент изначального массива. Практического смысла в этом немного, но сам механизм вы должны понимать - мы могли бы вставить вместо числа массив или объект, и функция map также заполнила бы результирующий массив указанными сущностями в соотношении 1</p>
28 <p>В этом примере мы даже не изменили, а заменили элементы. Функция вернула 5 на каждый элемент изначального массива. Практического смысла в этом немного, но сам механизм вы должны понимать - мы могли бы вставить вместо числа массив или объект, и функция map также заполнила бы результирующий массив указанными сущностями в соотношении 1</p>
29 <p>(один элемент изначального массива - один элемент конечного массива, вне зависимости от его внутренней сложности).</p>
29 <p>(один элемент изначального массива - один элемент конечного массива, вне зависимости от его внутренней сложности).</p>
30 <p>Вернемся к нашему массиву комментариев. Допустим, мы хотим получить коллекцию имен всех пользователей, которые отписались в вашем топике:</p>
30 <p>Вернемся к нашему массиву комментариев. Допустим, мы хотим получить коллекцию имен всех пользователей, которые отписались в вашем топике:</p>
31 <p>Отображение сработало как надо, и мы получили интересующие нас детали. Попробуйте самостоятельно извлечь из комментариев другие элементы. Измените их прямо в callback функции - к примеру, извлеките рейтинг пользователей и переведите его в двоичную систему счисления!</p>
31 <p>Отображение сработало как надо, и мы получили интересующие нас детали. Попробуйте самостоятельно извлечь из комментариев другие элементы. Измените их прямо в callback функции - к примеру, извлеките рейтинг пользователей и переведите его в двоичную систему счисления!</p>
32 <blockquote><h3>Читайте также:</h3>
32 <blockquote><h3>Читайте также:</h3>
33 <p><a>Что такое callback-функция</a>в JavaScript?</p>
33 <p><a>Что такое callback-функция</a>в JavaScript?</p>
34 </blockquote><h2>III. Reduce</h2>
34 </blockquote><h2>III. Reduce</h2>
35 <p>Функция reduce, наверное, самая сложная из нашей тройки, ведь, помимо элементов коллекции, в ней появляется аккумулятор, с которым нужно научиться правильно работать. Эта функция производит "свертку", то есть, берет элементы из коллекции и из их множества создает какую-то одну новую сущность. Например, из массива - объект или число.</p>
35 <p>Функция reduce, наверное, самая сложная из нашей тройки, ведь, помимо элементов коллекции, в ней появляется аккумулятор, с которым нужно научиться правильно работать. Эта функция производит "свертку", то есть, берет элементы из коллекции и из их множества создает какую-то одну новую сущность. Например, из массива - объект или число.</p>
36 <p>Технически функция reduce может заменить и filter, и map, но это, скорее всего, введет в заблуждение ваших коллег-программистов, поэтому старайтесь применять каждую функцию по прямому назначению. Для фильтрации - фильтрацию, для свертки - свертку.</p>
36 <p>Технически функция reduce может заменить и filter, и map, но это, скорее всего, введет в заблуждение ваших коллег-программистов, поэтому старайтесь применять каждую функцию по прямому назначению. Для фильтрации - фильтрацию, для свертки - свертку.</p>
37 <p>Теперь попробуем применить функцию reduce. Предположим, мы хотим, имея нашу коллекцию комментариев, создать объект, в котором ключами будут имена пользователей, а значениями - все комментарии данного пользователя.</p>
37 <p>Теперь попробуем применить функцию reduce. Предположим, мы хотим, имея нашу коллекцию комментариев, создать объект, в котором ключами будут имена пользователей, а значениями - все комментарии данного пользователя.</p>
38 <p>Давайте пошагово разберем, что здесь происходит.</p>
38 <p>Давайте пошагово разберем, что здесь происходит.</p>
39 <p>Из примечательного - у нас появляется аккумулятор. Это переменная, в которую мы будем складывать промежуточные результаты. Вспомните - функции высшего порядка обрабатывают элемент за элементом, а на выходе из reduce у нас должна получиться некая новая сущность. Ее мы будем наполнять последовательно, так что без аккумулятора не обойтись. В нашем случае переменная называется acc, но вы, конечно, можете придумать любое другое имя.</p>
39 <p>Из примечательного - у нас появляется аккумулятор. Это переменная, в которую мы будем складывать промежуточные результаты. Вспомните - функции высшего порядка обрабатывают элемент за элементом, а на выходе из reduce у нас должна получиться некая новая сущность. Ее мы будем наполнять последовательно, так что без аккумулятора не обойтись. В нашем случае переменная называется acc, но вы, конечно, можете придумать любое другое имя.</p>
40 <p>Во-вторых, у нас появляется инициализатор типа, к которому мы сводим коллекцию. В нашем случае это объект, поэтому ставим {}. На этом месте мог бы быть массив [], строка '' или число.</p>
40 <p>Во-вторых, у нас появляется инициализатор типа, к которому мы сводим коллекцию. В нашем случае это объект, поэтому ставим {}. На этом месте мог бы быть массив [], строка '' или число.</p>
41 <p>Теперь давайте разберемся с внутренней логикой callback функции.</p>
41 <p>Теперь давайте разберемся с внутренней логикой callback функции.</p>
42 <p>В нашем примере возможны два сценария: в объекте уже есть ключ (имя пользователя), и тогда мы должны добавить в значения новый комментарий; или в объекте еще нет такого ключа, и тогда нам нужно его создать.</p>
42 <p>В нашем примере возможны два сценария: в объекте уже есть ключ (имя пользователя), и тогда мы должны добавить в значения новый комментарий; или в объекте еще нет такого ключа, и тогда нам нужно его создать.</p>
43 <p>Что происходит здесь? Мы проверяем, есть ли в аккумуляторе искомый ключ. Для этого используем функцию _.has() из библиотеки Lodash. Если ключ есть, то добавляем текст комментария в значение ключа (оно представлено массивом).</p>
43 <p>Что происходит здесь? Мы проверяем, есть ли в аккумуляторе искомый ключ. Для этого используем функцию _.has() из библиотеки Lodash. Если ключ есть, то добавляем текст комментария в значение ключа (оно представлено массивом).</p>
44 <p>И возвращаем аккумулятор - это важно!</p>
44 <p>И возвращаем аккумулятор - это важно!</p>
45 <p>Если же ключа нет, тогда добавляем его в наш результирующий объект, и передаем ему значение - массив с одним элементом, то есть, первым найденным нами комментарием этого пользователя. А с помощью spread-оператора мы копируем в объект всю накопленную аккумулятором информацию. Не забываем про возврат.</p>
45 <p>Если же ключа нет, тогда добавляем его в наш результирующий объект, и передаем ему значение - массив с одним элементом, то есть, первым найденным нами комментарием этого пользователя. А с помощью spread-оператора мы копируем в объект всю накопленную аккумулятором информацию. Не забываем про возврат.</p>
46 <p>И вот он, долгожданный результат:</p>
46 <p>И вот он, долгожданный результат:</p>
47 <p>Как видите, из массива со множеством элементов мы создали один-единственный объект, зато наполнили его нужным нам содержимым. Попробуйте применить другую логику, например, вместо имени, используйте рейтинг пользователя.</p>
47 <p>Как видите, из массива со множеством элементов мы создали один-единственный объект, зато наполнили его нужным нам содержимым. Попробуйте применить другую логику, например, вместо имени, используйте рейтинг пользователя.</p>
48 <h2>IV. Бонус - функция forEach и особый синтаксис</h2>
48 <h2>IV. Бонус - функция forEach и особый синтаксис</h2>
49 <p>Среди функций высшего порядка есть еще один любопытный экземпляр, функция forEach. Она используется для перебора элементов массива прямо как цикл for...of. Но, в отличие от цикла, более гибко встраивается в синтаксис функций высшего порядка.</p>
49 <p>Среди функций высшего порядка есть еще один любопытный экземпляр, функция forEach. Она используется для перебора элементов массива прямо как цикл for...of. Но, в отличие от цикла, более гибко встраивается в синтаксис функций высшего порядка.</p>
50 <p>Особенность этого синтаксиса в том, что функции высшего порядка можно запускать последовательно, как методы, не создавая промежуточных констант:</p>
50 <p>Особенность этого синтаксиса в том, что функции высшего порядка можно запускать последовательно, как методы, не создавая промежуточных констант:</p>
51 <p>Не стану подробно расписывать этот пример, думаю, теперь вы можете провернуть такую операцию самостоятельно!</p>
51 <p>Не стану подробно расписывать этот пример, думаю, теперь вы можете провернуть такую операцию самостоятельно!</p>
52 <h2>Заключение</h2>
52 <h2>Заключение</h2>
53 <p>Спасибо, что прочитали эту статью! Надеюсь, функции высшего порядка стали вам немного понятнее и ближе. Практикуйтесь, и они станут вашими лучшими помощниками.</p>
53 <p>Спасибо, что прочитали эту статью! Надеюсь, функции высшего порядка стали вам немного понятнее и ближе. Практикуйтесь, и они станут вашими лучшими помощниками.</p>
54 <p>Желаю удачи в освоении JavaScript!</p>
54 <p>Желаю удачи в освоении JavaScript!</p>