Рубрики
Без рубрики

Функциональное программирование в JavaScript объяснено на простом английском

Одна из самых сложных вещей, которые вы должны сделать в программировании, является контроль сложности. Без тщательного рассмотрения, размер и сложность программы могут расти до того, как оно путает даже создателя программы. На самом деле, как один автор поставил это:

Автор оригинала: Joel P. Mugalu.

Одна из самых сложных вещей, которые вы должны сделать в программировании, является контроль сложности. Без тщательного рассмотрения, размер и сложность программы могут расти до того, как оно путает даже создателя программы.

На самом деле, как один автор поставил это:

В этой статье мы сломаем серьезную концепцию программирования. Эта концепция программирования может помочь вам поддерживать сложность под контролем и написать лучшие программы.

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

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

Если вы хотите быстрый обзор функций в JavaScript, то я написал подробную статью здесь Отказ

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

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

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

В функциональном программировании мы используем чистые функции, которые являются функциями, которые не имеют побочных эффектов. Я объясню, что все это значит.

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

Типы функций

Существует четыре основных типа функций.

Функции первого класса

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

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

Рассмотрим этот пример функции, передаваемой в переменной:

const helloWorld = () => {
	console.log("Hello, World"); // Hello, World
};
helloWorld();

Функции обратного вызова

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

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

Давайте посмотрим на пример:

const testValue = (value, test) => {
    if (test(value)) {
        return `${value} passed the test`;
    } else 
        return `${value} did not pass the test`;
};
const checkString = testValue('Twitter',  string  =>  typeof  string === 'string');
checkString; // Twitter passed the test

TestValue это функция, которая принимает значение и функцию обратного вызова Тест Что возвращается «значение» прошла тест «Если значение возвращает True при передаче в функцию обратного вызова.

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

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

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

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

Асинхронные функции

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

Идеальный пример асинхронной функции – это то, что мы написали ранее в статье.

const checkString = testValue('Twitter',  value  =>  typeof  value === 'string');
checkString;

// Refer to previous code snippet

Checkstring это переменная, значение которой является функцией. Продам два аргумента в эту функцию.

«Твиттер» это первый аргумент, а второй – асинхронная функция. Эта функция не имеет ни одного имени и имеет только одну задачу: проверить, является ли заданное значение строкой.

Принципы функционального программирования

Ранее в статье я ссылался на тот факт, что просто используя функции не переводит на функциональное программирование.

Существуют некоторые принципы, которые мы должны понимать, должны ли наши программы квалифицироваться для стандарта функционального программирования. Давайте посмотрим на те.

Избегайте мутаций и побочных эффектов.

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

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

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

Чистая функция не делает ни одного из двух. Чистая функция всегда будет иметь тот же выход для того же ввода.

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

Вот пример:

const legalAgeInTheUS = 21;
const checkLegalStatus = (age, legalAge) => {
    return age >= legalAge ? 'Of legal age.' : 'Not of legal age.';
};
const johnStatus = checkLegalStatus(18, legalAgeInTheUS);
johnStatus; // Not of legal age
legalAgeInTheUS; // 21

Абстракция

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

Мы используем абстракции во всех почти всех аспектах нашей жизни, особенно в речи.

Например, вместо того, чтобы сказать «Я собираюсь обменять деньги на машину, которая когда-то подключена к дисплеям, движущиеся изображения сопровождаются звуком» , вы, скорее всего, скажу «Я собираюсь купить телевизор» Отказ

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

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

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

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

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

Массивы фильтрации

При работе с структурами данных, такие как массивы, мы, скорее всего, найду себя в ситуации, когда нас интересуют только определенные предметы в массиве.

Чтобы получить эти элементы, мы можем легко создать функцию для выполнения задачи:

function filterArray(array, test) {
    const filteredArray = [];
    for (let item of array) {
        if (test(item)) {
            filteredArray.push(item);
        }
    }
    return filteredArray;
};
const mixedArray = [1, true, null, "Hello", undefined, "World", false];
const onlyStrings = filterArray(mixedArray, item => typeof item === 'string');
onlyStrings; // ['Hello', 'World']

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

Используя эту функцию, мы можем отфильтровать массив и возвращать элементы, которые нас интересуют, например, в случае Smickearray Отказ

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

К счастью, кто-то уже подумал об этом. Массивы имеют стандарт Фильтр метод. Он возвращает новый массив с элементами в массиве, который он получает, которые проходят тест, который мы предоставляем.

const mixedArray = [1, true, null, "Hello", undefined, "World", false];
const stringArray = mixedArray.filter(item => typeof item === 'string')
stringArray; // ['Hello', 'World']

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

Преобразование предметов массива с картой

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

function transformArray(array, test) {
    const transformedArray = [];
    for (let item of array) {
        transformedArray.push(test(item));
    }
    return transformedArray;
};
const ages = [12, 15, 21, 19, 32];
const doubleAges = transformArray(ages, age => age * 2);
doubleAges; // [24, 30, 42, 38, 64];

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

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

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

const ages = [12, 15, 21, 19, 32];
const doubleAges = ages.map(age => age * 2);
doubleAges; // [24, 30, 42, 38, 64];

Уменьшение массивов с уменьшением

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

function reduceArray(array, test, start) {
    let sum = start;
    for (let item of array) {
        sum = test(sum, item)
    }
    return sum;
}
let numbers = [5, 10, 20];
let doubleNumbers = reduceArray(numbers, (a, b) => a + b, 0);
doubleNumbers; // 35

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

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

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

let numbers = [5, 10, 20];
let doubleNumbers = numbers.reduce((a, b) => a + b, 10);
doubleNumbers;  // 45

//The above example uses the reduce method to add all the items in the array starting from 10.

Другие полезные методы массива

Array.some ()

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

const numbers = [12, 34, 75, 23, 16, 63]
console.log(numbers.some(item => item < 100)) // true

Array.ewyy ()

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

const numbers = [12, 34, 75, 23, 16, 63]
console.log(numbers.every(item => item < 100)) // true

Array.concat ()

Concat Метод, короткий для ConcateNate, является стандартным методом массива, который объединяет или присоединяется к двум массивам и возвращает новый массив:

const array1 = ['one', 'two', 'three'];
const array2 = ['four', 'five', 'six'];
const array3 = array1.concat(array2);
array3; // [ 'one', 'two', 'three', 'four', 'five', 'six' ]

Array.slice ()

ломтик Метод – это метод массива, который копирует элементы массива из данного индекса и возвращает новый массив с скопированными элементами. ломтик Метод принимает два аргумента.

Первый аргумент получает индекс, с которого можно начать копирование. Второй аргумент получает индекс, из которого прекратить копирование. Он возвращает новый массив с скопированными элементами из исходного индекса (Exclusive) до конечного индекса (включительно).

Обратите внимание, однако, что метод ломтика не использует нулевую индексацию. Таким образом, индекс первого элемента массива 1 не 0:

const numbers = [1,2,3,4,5,7,8];
console.log(theArray.slice(1, 4)); // [ 2, 3, 4 ]

Заключение

Я надеюсь, что вам понравилось читать эту статью и узнал что-то новое одновременно.

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

Если вы хотите связаться со мной или просто сказать привет? Не стесняйтесь сделать это через Twitter Отказ Я также делюсь интересными советами и ресурсами для разработчиков. ?

Оригинал: “https://www.freecodecamp.org/news/functional-programming-in-javascript-explained-in-plain-english/”