RU EN

«Чистые» и «нечистые» функции в JavaScript

Автор:
Alex Myzgin
Источник:
Просмотров:
1626
«Чистые» и «нечистые» функции в JavaScript favorites 0

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

  • функции, вывод которых зависит от внешнего / глобального состояния;
  • функции, которые возвращают разные исходные данные при одинаковых входных;
  • функции, которые изменяют состояние приложения;
  • функции, которые изменяют «внешний мир».

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

«Чистая» функция - это функция, которая выводит свои данные основываясь исключительно на свои входные данные и не вызывает побочных эффектов в приложении.

Например у нас есть функция, которая получает одно значение x и возвращает в данном случае x + 1:

// function f(x) { return x + 1 }

const f = x => x + 1;

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

Первая «нечистая» функция

Первая «нечистая» функция, которую мы собираемся сделать - это та, чей результат не основан исключительно на её входных данных. Например, давай рассмотрим функцию totalPrice. У нас есть глобальная переменная COST_OF_ITEM, которая содержит цену на товар. Функция totalPrice берет quantity и умножает ее на эту переменную.

// Глобальная переменная

const COST_OF_ITEM = 250;

const totalPrice = quantity => COST_OF_ITEM * quantity;

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

// Глобальная переменная

const COST_OF_ITEM = 250;

const totalPrice = quantity => COST_OF_ITEM * quantity;

console.log(totalPrice(2)); // 500
console.log(totalPrice(2)); // 500

Хоть мы и получаем тот же результат, но это «нечистая» функция, так как состояние нашего приложения влияет на вывод нашей функции. Мы можем увидеть это, изменив значение COST_OF_ITEM и посмотреть снова в консоль.

const COST_OF_ITEM = 200;

const totalPrice = quantity => COST_OF_ITEM * quantity;

console.log(totalPrice(2)); // 400
console.log(totalPrice(2)); // 400

Вторая «нечистая» функция

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

Давай создадим функцию generateID. Эта функция будет возвращать целое число в случайном порядке. Это «нечистая» функция, так как вызвав её несколько раз, каждый раз мы получим разный результат.

const generateID = () => Math.floor(Math.random() * 10000);

console.log(generateID()); // 7602
console.log(generateID()); // 1377
console.log(generateID()); // 7131

Давай используем нашу «нечистую» функцию generateID внутри фабричной функции для создания пользовательских объектов. Чтобы создать пользователя, createUser принимает два параметра: name и age, и возвращает объект с id, используя функцию generateID для его создания, а также name и age.

const generateID = () => Math.floor(Math.random() * 10000);

const createUser = (name, age) => ({
id: generateID(),
name,
age
});

Вызовем createUser несколько раз, с одинаковыми аргументами.

const generateID = () => Math.floor(Math.random() * 10000);

const createUser = (name, age) => ({
id: generateID(),
name,
age
});
console.log(createUser("Alex", 28)); // {id: 3141, name: "Alex", age: 28}
console.log(createUser("Alex", 28)); // {id: 9646, name: "Alex", age: 28}
console.log(createUser("Alex", 28)); // {id: 9218, name: "Alex", age: 28}

Если посмотрим в консоль, то увидим, что мы получили похожие объекты, но они не одинаковые - id у всех разный.

«Нечистота» функции generateID делает нашу фабричную функцию createUser «нечистой». Для того чтобы исправить это - можно переместить «нечистую» функцию за пределы фабрики и вызвать её где-нибудь, где мы ожидаем побочный эффект, и передать id в качестве параметра в нашу фабрику createUser.

Третья «нечистая» функция

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

Допустим, мы отслеживаем изменяемое значение (в данном случае id). Если мы создадим функцию, которая изменяет это значение, у нас будет «нечистая» функция. Например фабричная функция createPersone.

let id = 0;

const createPersone = name => ({
id: ++id,
name
});

Если мы генерируем наш id для этого объекта, изменяя значение глобального id, то это «нечистая» функция. Вызвав эту функции несколько раз с разными name, то увидим, что id увеличился как мы и ожидали, но если мы также выведем в консоль глобальное значение id, то увидим, что оно тоже изменилось.

let id = 0;

const createPersone = name => ({
id: ++id,
name
});

console.log(createPersone("Alex")); // {id: 1, name: "Alex"}
console.log(createPersone("Julia")); // {id: 2, name: "Julia"}
console.log(id); // 2

Четвертая «нечистая» функция

Последний четвертый пример «нечистой» функции - это побочный эффект “внешнего мира”. console.log - «нечистая» функция, так как она создает побочный эффект во “внешнем мире”.

Каждый раз, когда мы используем console.log, это влияет на нашу консоль, а это побочный эффект. Если у нас есть какая-либо функция, использующая console.log, (например, функция logger, которая принимает сообщение и выводит его) это тоже «нечистая» функция.

const logger = msg => {
console.log(msg);
};

logger("Всем привет!"); 

Похожее
24 марта 2024 г.
Автор: Артём Полищук
Когда вам нужно что-то отдебажить на фронтенде, вы юзаете console.log Одной из проблем юзания console.log может быть "засорение" консоли, что затрудняет чтение консоли. Ниже обсудим 10 способов как улучшить запись в консоль: 1. console.table Вместо того, чтобы просто выводить массив...
Dec 26, 2024
Author: Onix React
JavaScript is one of the most popular programming languages in web development, known for its flexibility and wide application across browsers and servers. But with great power comes great responsibility — maintaining clean, efficient, and readable code is crucial, especially...
Feb 3, 2022
Author: Satish Chandra Gupta
What if programming languages were stocks? And you had to make a portfolio to fetch good returns in 2022? You probably have seen various surveys and analyses listing the most popular programming languages. Those cover the universe of programming languages,...
Oct 31, 2024
Author: Dante J. Anjos
In this post I want to show how we can easily create a modal with vanilla JavaScript. It can have multiple open/close handlers thanks to querySelectorAll. First of all lets create the HTML structure for our modal. <div class="modal">  ...
Написать сообщение
Тип
Почта
Имя
*Сообщение
RSS
Если вам понравился этот сайт и вы хотите меня поддержать, вы можете
Почему сеньоры ненавидят собеседования с кодингом, и что компании должны использовать вместо них
Топ 20 ботов которые постоянно сканируют ваши сайты. Не все из них одинаково полезны
Hangfire — планировщик задач для .NET
GraphQL решает кучу проблем — рассказываем, за что мы его любим
Не одними Unity и Unreal Engine. Альтернативные игровые движки
Почему As Code — это не просто тренд, а новая реальность разработки
Soft skills: 18 самых важных навыков, которыми должен владеть каждый работник
WAF и RASP: в чём разница и что лучше для безопасности веб-приложений
Функции и хранимые процедуры в PostgreSQL: зачем нужны и как применять в реальных примерах
Как сделать полезный дашборд: советы и идеи
Boosty
Donate to support the project
GitHub account
GitHub profile