Иммутабельность и мутабельность в JavaScript
В JavaScript данные можно изменять двумя способами: мутабельно и иммутабельно. Понимание разницы между ними особенно важно при работе с состоянием (state) в React, Redux и других библиотеках.
Мутабельность (mutability)
Мутабельность означает, что объект может быть изменён после создания.
const user = { name: "Alice" };
user.name = "Bob"; // изменяем напрямую
console.log(user); // { name: "Bob" }
Такие изменения происходят по ссылке, и могут вызывать непредсказуемое поведение, особенно если один и тот же объект используется в нескольких места
Иммутабельность (immutability)
Иммутабельность означает, что объект не изменяется, а при изменениях создаётся новая копия.
const user = { name: "Alice" };
const updatedUser = { ...user, name: "Bob" }; // создаём новый объект
console.log(user); // { name: "Alice" }
console.log(updatedUser); // { name: "Bob" }
Иммутабельность делает данные предсказуемыми и безопасными для сравнения, что критично при ререндеринге компонентов в React
.
Иммутабельность в React
React
не отслеживает изменения по содержимому объектов, он сравнивает их по ссылке (===
).
Поэтому мутабельное обновление не вызовет ререндер:
// неправильный подход
state.items.push("newItem");
setState(state); // ссылка та же → React не обновит компонент
Правильный иммутабельный способ:
// создаём новый массив
setState({ ...state, items: [...state.items, "newItem"] });
Сравнение
Свойство | Мутабельность | Иммутабельность |
---|---|---|
Изменение данных | Вносится прямо в объект | Создаётся новая копия |
Поведение в React | Может не вызвать ререндер | Всегда надёжно вызывает ререндер |
Безопасность данных | Возможны побочные эффекты | Данные защищены от мутаций |
Удобство отладки | Труднее отслеживать | Легче отслеживать изменения |
Примеры иммутабельных операций:
// массивы
const newArr = [...oldArr, newItem];
const filtered = oldArr.filter(item => item !== target);
// объекты
const newObj = { ...oldObj, updatedKey: newValue };
// вложенные объекты
const updated = {
...state,
user: {
...state.user,
name: "John",
},
};
Вывод:
Используйте иммутабельность, чтобы сделать код предсказуемым, безопасным и совместимым с React. Это основа корректной работы useEffect
, React.memo
, Redux и других инструментов.