Иммутабельность, каррирование и композиция
Понятия из функционального стиля, которые любят спрашивать «на понимание».
Иммутабельность — подход, при котором данные не меняют, а создают их новую версию. Это упрощает отслеживание изменений и предотвращает «неожиданные» мутации.
Мутация против иммутабельного обновления
Мутирующие методы (push, splice, присваивание свойств) меняют исходные данные. Иммутабельный подход возвращает новый объект/массив, не трогая старый.
const state = { count: 1, items: ["a"] };
// иммутабельно: новый объект через spread
const next = { ...state, count: 2 };
console.log(state.count); // старое не изменилось
console.log(next.count);
console.log(state === next);
Вывод:
1 2 false
Иммутабельные методы массива
map, filter, concat, slice, spread — не мутируют. push, splice, sort — мутируют. Это важно помнить, чтобы случайно не испортить общий массив.
const arr = [3, 1, 2];
const sortedCopy = [...arr].sort(); // сначала копия, потом sort
console.log(sortedCopy);
console.log(arr); // оригинал цел
const without2 = arr.filter((x) => x !== 2); // новый массив
console.log(without2);
console.log(arr);
Вывод:
[ 1, 2, 3 ] [ 3, 1, 2 ] [ 3, 1 ] [ 3, 1, 2 ]
Object.freeze: запрет на мутацию
Object.freeze делает объект неизменяемым на верхнем уровне: попытки изменить свойства молча игнорируются (в нестрогом режиме).
const config = Object.freeze({ debug: false });
config.debug = true; // игнорируется
console.log(config.debug);
console.log(Object.isFrozen(config));
Вывод:
false true
Каррирование
Каррирование — превращение функции от нескольких аргументов в цепочку функций по одному аргументу. Помогает «частично применять» функцию.
const add = (a) => (b) => (c) => a + b + c;
console.log(add(1)(2)(3));
const add10 = add(10); // зафиксировали первый аргумент
console.log(add10(20)(30));
Вывод:
6 60
Композиция функций
Композиция объединяет несколько функций в одну: выход одной становится входом следующей.
const compose = (...fns) => (x) =>
fns.reduceRight((acc, fn) => fn(acc), x);
const inc = (n) => n + 1;
const double = (n) => n * 2;
const incThenDouble = compose(double, inc); // сначала inc, потом double
console.log(incThenDouble(5)); // (5+1)*2
Вывод:
12
Итог
- Иммутабельность — не менять данные, а создавать их новую версию.
map/filter/spread не мутируют;push/sort/splice— мутируют.- Каррирование разбивает аргументы по одному; композиция соединяет функции в конвейер.