Концепции функционального программирования с практическими примерами

Что такое функциональное программирование?

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

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

В этой статье мы рассмотрим некоторые полезные концепции функционального программирования на JavaScript. Давайте приступим к делу.

1. Чистые функции

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

Первая версия:

let age = 19

function getMyAge() {
  console.log(`I'm ${age} years old.`)
}

getMyAge(age) //Returns: I'm 19 years old.
age = 20
getMyAge(age) //Returns: I'm 20 years old.

Вторая версия:

function getMyAge(age) {
  return `I'm ${age} years old.`
}

getMyAge(19) //Returns: I'm 19 years old.
getMyAge(20) //Returns: I'm 20 years old.

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

2. Побочные эффекты

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

var double = function(value){
    return value * 2;
}
var initialValue = 30;
double(initialValue); // 60
initialValue; // Still 30.

3. Изменчивость

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

Изменяемый пример:

function changeFirstElem(array) {
  array[0] = 'Lose yourself to dance'
}

const daftPunkPopSongs = ['Instant Crush', 'Get Lucky', 'One More Time'];
changeFirstElem(daftPunkPopSongs);
console.log(daftPunkPopSongs); // ["Lose yourself to dance", "Get Lucky", "One More Time"].

Неизменяемый пример:

function changeFirstElem(array) {
  const modifiedArray = ['Lose yourself to dance', ...array];
  return modifiedArray;
}

const daftPunkPopSongs = ['Instant Crush', 'Get Lucky', 'One More Time'];
const modifiedArray = changeFirstElem(daftPunkPopSongs);
Console.log(daftPunkPopSongs); // Returns: ['Instant Crush', 'Get Lucky', 'One More Time'].

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

4. Функции высшего порядка.

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

Вот некоторые из важных функций, которые вам следует знать:

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

const numbers = [1, 2, 3];
const doubles = numbers.map(num => num * 2) //[2, 4, 6]

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

const numbers = [1, 2, 3];
const isGreaterThanOne = numbers.filter(num => num > 1) //[2, 3]

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

const numbers = [1, 2, 3];
const mySum = numbers.reduce((accumulator, num) => accumulator + num) // returns: 6.

5. Каррирование и частичное применение

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

//Un-curried function
function unCurried(x, y) {
  return x + y;
}

//Curried function
function curried(x) {
  return function(y) {
    return x + y;
  }
}
//Alternative using ES6
const curried = x => y => x + y

curried(1)(2) // Returns 3

Каррирование полезно в вашей программе, если вы не можете передать все аргументы функции одновременно.

Теперь давайте посмотрим на Частичное приложение, которое можно описать как применение нескольких аргументов к функции за раз и возвращение другой функции, которая применяется к большему количеству аргументов. Вот пример:

//Impartial function
function impartial(x, y, z) {
  return x + y + z;
}
var partialFn = impartial.bind(this, 1, 2);
partialFn(10); // Returns 13

Заключение

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

Спасибо, что прочитали эту статью, надеюсь, вы нашли ее полезной. Если да, то получите больше похожего контента, подписавшись на наш канал на YouTube в Decoded!

Больше Чтения