«Чистые функции» и «нечистые функции» - эти два термина программирования, которые вы можете довольно часто встречать в рамках функционального программирования.
Основное различие между ними заключается в том, что одни из них имеют побочные эффекты, а другие – нет.
В рамках этой статьи мы расскажем, что такое побочные эффекты, и также посмотрим, в чем же разница между чистыми и нечистыми функциями.
Без лишних слов, давайте приступим. Начнем с того, что же такое побочные эффекты.
Что такое побочный эффект?
Побочный эффект – это последствие использования внешнего кода в функции, что в результате сказывается на способности функции выполнять свою задачу.
Итак, что же это значит на самом деле? Давайте взглянем на несколько примеров.
Побочный эффект. Пример 1: как заменить старое значение на новое
let oldDigit = 5;
function addNumber(newValue) {
return oldDigit += newValue;
}
Использование переменной oldDigit внутри функции addNumber() в приведенном выше фрагменте кода дает следующие побочные эффекты:
Первый побочный эффект: зависимость от переменной oldDigit
Тот факт, что успешное выполнение функции addNumber() зависит от переменной oldDigit, означает, что всякий раз, когда переменная oldDigit недоступна (или не определена (undefined)), функция addNumber() вернет ошибку.
Второй побочный эффект: изменение внешнего кода
Функция addNumber() запрограммирована на то, чтобы менять значение переменной oldDigit, а это значит, что функция addNumber() имеет побочный эффект, связанный с воздействием на внешний код.
Третий побочный эффект: функция становится недетерминированной
Функция addNumber() используется внешний код, а, значит, она является недерминированной, поскольку вы не сможете определить, что она выведет в качестве результата, просто прочитав ее.
Иными словами, чтобы точно знать, что выведет функция addNumber(), вы должны учитывать внешние факторы, такие как текущее значение переменной oldDigit.
А значит, функцию addNumber() нельзя считать независимой, так как она связана с другими строками.
Побочный эффект. Пример 2: как вывести текст в консоль
function printName() {
console.log("My name is Oluwatobi Sofela.");
}
Использование console.log() в функции printName() в приведенном выше фрагменте кода дает побочные эффекты.
Каким образом console.log вызывает у функции побочный эффект?
console.log() дает побочные эффекты, так как влияет на состояние внешнего кода, то есть на состояние объекта console.
Иными словами, console.log() дает компьютеру указание изменить состояние объекта console.
В связи с этим, когда вы используете console.log() внутри функции, происходит следующее:
- Эффективное выполнение работы функции начинает зависеть от объекта console.
- Функция меняет состояние внешнего кода (то есть состояние объекта console).
- Функция становится недетерминированной, то есть теперь, чтобы точно знать, что выведет функция, вам нужно учитывать состояние объекта console.
В результате чего, всякий раз, когда вы будете использовать внешний код в вашей функции, он будет вызывать побочные эффекты.
Так каким же образом побочные эффекты имеют отношение к чистым и нечистым функциям?
Давайте узнаем это. Для этого взглянем на определение чистой функции и ее альтернативы – нечистой функции.
Что такое «нечистая» функция?
Итак, мы уже знаем, что такое побочные эффекты в функциях, и теперь мы можем поговорить о том, что же такое нечистые (и чистые) функции.
Для начала, нечистая функция – это функция, в которое есть один или несколько побочных эффектов.
Давайте посмотрим на код JavaScript, представленный ниже:
const myNames = ["Oluwatobi", "Sofela"];
function updateMyName(newName) {
myNames.push(newName);
return myNames;
}
Функция updateMyName() в приведенном выше фрагменте кода – это нечистая функция, так как она содержит код (myNames), который меняет состояние внешнего кода, что дает побочные эффекты.
Что такое «чистая» функция?
Чистая функция – это функция, у которой нет никаких побочных эффектов.
Давайте посмотрим на код JavaScript, представленный ниже:
function updateMyName(newName) {
const myNames = ["Oluwatobi", "Sofela"];
myNames[myNames.length] = newName;
return myNames;
}
Обратите внимание, что выполнение функции updateMyName() в приведенном выше фрагменте кода не зависит ни от какого внешнего кода. За счет этого эта функция является чистой.
При написании приложения чистые функции нужно использовать везде, где это возможно. Давайте разберем некоторые преимущества, которые вы получит от их использования.
Преимущества «чистых» функций
Ниже представлены некоторые преимущества чистых функций.
Чистые функции – независимы
Чистые функции не влияют ни на что, что находится за ее пределами, и ничто, что находится за ее пределами, не влияет на нее.
Иными словами, все внешние данные, которые использует чистая функция, передаются ей в качестве параметров, а не используются явно внутри нее.
Так что, все, что вы видите внутри функции, - это то, что вы вычисляете, и никаких связанных строк.
Соответственно, вам не нужно искать какие-то внешние условия (состояния), которые могут как-то повлиять на эффективную работу чистой функции, так как все действия происходят внутри этой функции.
Чистые функции проще читать
Чистые функции намного проще читать и отлаживать, нежели их альтернативный вариант – нечистые функции.
Эти функции легко читать, поскольку они зависят только от самих себя – они не влияют на внешние состояния, и внешние состояния не влияют на них.
Важная информация о чистых функциях
Если вы используете чистые функции, не забывайте об этих трех важных фактах.
Вы можете клонировать внешний объект в чистую функцию
Клонирование внешнего объекта в чистую функцию не сделает функцию нечистой.
Дублирование объекта – это просто операция копирования и вставки, которая не оставляет никаких связей между исходным объектом и клоном.
Пример:
const myBio = ["Oluwatobi", "Sofela"];
function updateMyBio(newBio, array) {
const clonedBio = [...array];
clonedBio[clonedBio.length] = newBio;
return clonedBio;
}
console.log(updateMyBio("codesweetly.com", myBio));
Функция updateMyBio() в приведенном выше фрагменте кода использует spread-оператор для того, чтобы продублировать состояние myBio в clonedBio. И тем не менее, это все еще чистая функция, так как она не зависит ни от myBio, ни от какого-либо другого внешнего кода.
Напротив, это всецело детерминированная функция, которая запрограммирована на то, чтобы использовать клонированную версию своего массива.
Избегайте изменений кода в чистых функциях
Чисто технически вы можете менять переменные, которые определены локально в области действия чистой функции. Но все же этого лучше не делать.
Давайте в качестве примера посмотрим на следующий код:
const compBio = ["code", "sweetly"];
function updateCompBio(newBio, array) {
const clonedBio = [...array];
clonedBio[clonedBio.length] = newBio;
return clonedBio;
}
console.log(updateCompBio(".com", compBio));
Функция updateCompBio() в приведенном выше фрагменте кода – это чистая функция, которая использует строку clonedBio[clonedBio.length] = newBio для того, чтобы изменить свое локальное состояние.
Несмотря на то, что функция updateCompBio() не стала от этого нечистой, так лучше не делать.
Лучше всего, чтобы чистая функция принимала все свои значения в качестве параметров, то есть:
const compBio = ["code", "sweetly"];
function updateCompBio(newBio, array) {
return [...array, newBio];
}
console.log(updateCompBio(".com", compBio));
Обратите внимание, каким чистым и негромоздким стал наш код. Это благодаря тому, что наша чистая функция получает все свои значения в качестве параметров. Так вам даже будет легче отлаживать код.
Один и тот же набор входных данных возвращает один и тот же результат
У чистых функций есть одна очень важная особенность – они всегда возвращают одно и то же значения для одних и тех же наборов данных, и абсолютно неважно, сколько раз вы вызываете эту функцию.
Заключение
Ваша функция – чистая, если в ней нет никакого внешнего кода. В противном случае, если в ней есть один или несколько побочных эффектов, эта функция является нечистой.
В этой статье мы поговорили о том, что такое чистые и нечистые функции, а также выяснили, какие есть преимущества у использования чистых функций.