Функциональное программирование - одна из самых популярных сейчас тенденций, и есть много хороших аргументов в пользу того, почему можно использовать его в своем коде. Я не собираюсь вдаваться в подробности обо всех концепциях и идеях функционального программирования, однако я постараюсь предоставить наглядное руководство по использованию функционального программирования в повседневных ситуациях, связанных с Javascript .

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

Переопределение функций

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

Так, например, в Javascript вы можете сделать это:

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



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

Использование встроенных методов прототипа массива

Array.prototype - это то, с чего вам следует начать, когда вы приступите к функциональному программированию на Javascript. Он содержит множество полезных методов для применения преобразований к массивам, что является очень распространенным сценарием использования в большинстве современных приложений.



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

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

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

Сортировка - не единственное, что вы часто делаете в массиве. По моему опыту, f фильтрация массива на основе свойства довольно распространено, и что может быть лучше для фильтрации массива, чем Array.prototype.filter(). Фильтровать несложно, так как вам нужно только передать функцию в качестве аргумента, которая вернет false для любых элементов, которые необходимо отфильтровать, иначе она вернет true. Все просто, правда? Давайте посмотрим на это на практике:

В то время как .filter() возвращает все элементы в массиве, которые соответствуют условию, вы также можете использовать Array.prototype.find(), чтобы получить только первый элемент в массиве, который соответствует условию, или Array.prototype.findIndex(), чтобы получить индекс первого сопоставленного элемента в массиве. Точно так же вы можете использовать Array.prototype.some(), чтобы проверить, соответствует ли хотя бы один элемент заданному условию, и Array.prototype.every(), чтобы увидеть, все ли элементы массива соответствуют условию. Они могут быть особенно полезны в некоторых приложениях, поэтому давайте рассмотрим пример, использующий комбинацию этих методов:

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

Отступив от сложной логики предыдущего примера, мы иногда хотим просто преобразовать массив в другой с большим или меньшим количеством полей, не изменяя при этом данные. Здесь на помощь приходит Array.prototype.map(), позволяющий преобразовывать объекты в массиве. Разница между .map() и предыдущими методами заключается в том, что функция высшего порядка, которую он использует в качестве аргумента, должна возвращать объект, который может быть практически любым, что вы хотите. Позвольте мне продемонстрировать на простом примере:

В приведенном выше примере, применив .map() к нашему массиву, мы легко получили массив, объекты которого содержат только желаемые свойства. В этом случае нам нужно только строковое представление полей name и surname объектов, поэтому мы создали массив строк из массива объектов, используя простое отображение. Сопоставление встречается чаще, чем вы думаете, и оно может быть очень мощным инструментом в арсенале каждого веб-разработчика, поэтому, если есть один вывод из этой статьи, вам следует научиться использовать .map().

И последнее, но не менее важное: вам следует обратить внимание на преобразование массива общего назначения, равное Array.prototype.reduce(). .reduce() немного отличается от всех других методов, упомянутых выше, поскольку он использует функцию высшего порядка в качестве аргумента, а также аккумулятор. Сначала это может показаться немного запутанным, поэтому пример должен помочь вам понять основную идею .reduce():

Приведенный выше пример не должен особенно сбивать с толку тех, кому когда-либо приходилось суммировать значения массива. Сначала мы определяем многократно используемую функцию высшего порядка, которую мы используем для суммирования значений каждого массива. Затем мы фактически используем эту функцию для суммирования значений первого массива, а затем, используя уже накопленное значение суммы первого массива в качестве начального значения, мы передаем эту сумму второй функции суммирования массива, чтобы все значения в к нему будет добавлен второй массив вместо нуля.



Reduce (Программное обеспечение для создания композиций)
Примечание. Это часть серии« Программное обеспечение для создания композиций
, посвященной изучению функционального программирования и программного обеспечения для композиции… medium.com»



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

Приведенный выше пример может показаться немного более сложным, чем он есть на самом деле, поэтому давайте разберемся с ним. Во-первых, мы хотим получить массив в качестве окончательного результата, поэтому начальное значение нашего аккумулятора будет []. Затем мы хотим, чтобы каждый объект в массиве содержал имя тега, количество и фактический список статей. Мы также знаем, что каждый тег должен появляться в массиве только один раз, поэтому нам нужно будет проверить, существует ли он, используя .some(), .find() и .findIndex(), как раньше, чтобы преобразовать существующий объект тега вместо добавления нового.

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



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

В заключение

Функциональное программирование - одна из самых горячих тенденций прямо сейчас, и не зря. Это позволяет нам писать более чистый, компактный и средний код, не беспокоясь о побочных эффектах и ​​изменении состояния. Array.prototype методы Javascript действительно полезны во многих повседневных ситуациях и позволяют применять простые и сложные преобразования к массивам без повторения.