Чиста функція
Чиста функція (pure function), це функція, яка завжди повертає той самий результат для тих самих вхідних даних і не має побічних ефектів. Тобто вона не змінює зовнішні змінні, DOM, файли, мережу і взагалі нічого за своїми межами.
Теорія
TL;DR
- Чиста функція детермінована: однаковий вхід завжди дає однаковий вихід.
- Чиста функція не має побічних ефектів: нічого не змінює поза собою.
- Вона не залежить від зовнішнього стану, тому передбачувана і тестована.
- Нечистими роблять: зміна зовнішніх змінних, DOM, файли, мережа,
console.log(). - Також нечисті
Math.random()іDate.now(), бо результат щоразу інший. - Чисті функції легко кешувати (memoization) і безпечно виконувати паралельно.
- Це фундаментальне поняття функціонального програмування.
Швидкий приклад
// Чиста функція
function add(a, b) {
return a + b;
}
// Нечиста функція
let counter = 0;
function increase() {
counter++; // побічний ефект: змінює зовнішню змінну
return counter;
}Дві ключові ознаки
Чиста функція, це фундаментальне поняття функціонального програмування. Вона передбачувана, тестована і не залежить від зовнішнього стану.
- Детермінованість. Один і той самий ввід завжди дає один і той самий вивід.
- Відсутність побічних ефектів. Функція не змінює нічого за своїми межами.
Обидві ознаки обов'язкові. Функція, що повертає стабільний результат, але дорогою пише щось у лог або в глобальний об'єкт, уже нечиста.
Приклад чистої функції
function add(a, b) {
return a + b;
}Завжди повертає однаковий результат і нічого не змінює в зовнішньому світі. Її можна викликати скільки завгодно разів у будь-якому порядку, і поведінка програми від цього не зміниться.
Приклад нечистої функції
let counter = 0;
function increase() {
counter++; // побічний ефект: змінює зовнішню змінну
return counter;
}Ця функція нечиста, бо її результат залежить від зовнішнього стану (counter) і вона цей стан змінює. Два однакові виклики increase() дадуть різні значення, і це вже порушує детермінованість.
Інші приклади нечистих функцій
- читання або запис у файл чи базу даних;
- зміна DOM;
- виклик
alert()абоconsole.log(); - використання випадкових чисел (
Math.random()); - використання поточного часу (
Date.now()).
Окремий випадок, це мутація аргументів: якщо функція змінює переданий їй об'єкт чи масив, вона теж нечиста, навіть якщо не чіпає жодної глобальної змінної.
// Нечиста: мутує вхідний масив
function addItemImpure(list, item) {
list.push(item);
return list;
}
// Чиста: повертає нову копію
function addItem(list, item) {
return [...list, item];
}Навіщо потрібні чисті функції
- Легко тестувати, бо результат залежить лише від аргументів.
- Легко кешувати (memoization).
- Безпечні для паралельного виконання.
- Підвищують передбачуваність і читабельність коду.
| Властивість | Чиста функція |
|---|---|
| Повертає однаковий результат | Так |
| Залежить від зовнішніх змінних | Ні |
| Змінює зовнішній стан | Ні |
| Приклад | Math.max(1, 5) |
| Протилежність | «Брудна» функція з побічними ефектами |
Чиста функція, це функція, яка не впливає на зовнішній світ і завжди поводиться однаково за однакового вводу.
Типові помилки
- Вважати чистою функцію, яка мутує аргумент.
list.push(item)змінює об'єкт викликача, тож це побічний ефект. - Забувати про
console.log(). Формально це вивід назовні, тому суворо кажучи функція з логуванням уже нечиста. - Плутати чистоту з відсутністю
return. Чистота про детермінованість і побічні ефекти, а не про наявність результату. - Використовувати
Date.now()абоMath.random()всередині. Такі значення передають аргументом, і тоді функція знову стає чистою і тестованою. - Намагатися зробити чистою всю програму. Побічні ефекти потрібні, щоб вона хоч щось робила; їх виносять на межі застосунку, а ядро логіки лишають чистим.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.