webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
JavaScript · Урок 10 из 17

Ссылки и иммутабельность

Значение и ссылка, иммутабельные обновления, поверхностная и глубокая копия.

Обновлено

Что значат «значение» и «ссылка»

Когда вы присваиваете значение переменной, JS делает одно из двух, в зависимости от типа:

По значению По ссылке
Типы примитивы: string, number, boolean, null, undefined объекты, массивы, функции
Что копируется само значение адрес того же значения в памяти
Эффект две независимые копии два имени для одного и того же объекта
let a = 1
let b = a
b = 2
a          // 1 — независимые копии

const x = { count: 1 }
const y = x            // y указывает на тот же объект, что и x
y.count = 2
x.count    // 2 — это один и тот же объект!

Аналогия: примитивы — как ксерокопия листа; объекты — как ссылка на Google Doc: вы отправляете ссылку, а не сам документ.

Сравнение подчиняется тому же правилу

'a' === 'a'            // true — сравниваются значения
{ a: 1 } === { a: 1 }  // false — два разных объекта, разные адреса
const o = {}; o === o  // true — один и тот же адрес

Что такое иммутабельность

Иммутабельно = вы не меняете существующий объект, а создаёте новый с изменением. Противоположность — мутация, изменение на месте.

// мутация
user.age = 31

// иммутабельно
const updated = { ...user, age: 31 }

Почему это важно — особенно в React

React решает, перерисовывать ли, сравнивая старое и новое состояние по ссылке (Object.is). Если изменить объект на месте, ссылка та же → React думает, что ничего не изменилось → интерфейс не обновляется.

// ✗ мутация: та же ссылка, перерисовки нет
todos.push(newTodo)
setTodos(todos)

// ✓ новый массив
setTodos([...todos, newTodo])

Другие плюсы: можно быстро проверить «изменилось ли?», есть история (undo), нет скрытых эффектов между частями кода, которые делят один объект.

Шпаргалка: иммутабельные обновления

Операция Массив Объект
добавить [...arr, x] { ...obj, key: v }
удалить arr.filter(x => x.id !== id) const { key, ...rest } = obj
изменить один arr.map(x => x.id === id ? { ...x, done: true } : x) { ...obj, key: v }
отсортировать arr.toSorted(fn) —
по индексу arr.with(i, v) —
вложенное — { ...obj, address: { ...obj.address, city } }

Поверхностная и глубокая копия

Поверхностная (shallow) Глубокая (deep)
Как { ...obj }, [...arr], Object.assign structuredClone(obj)
Что копирует только первый уровень; вложенные объекты остаются общими всё, на любой глубине
Стоимость маленькая больше
Когда обновления состояния (копируете только то, что меняете) когда действительно нужна независимая копия
const copy = { ...user }
copy.address.city = 'Самара'   // ✗ меняет и user.address — это тот же объект

const deep = structuredClone(user)
deep.address.city = 'Самара'   // ✓ user не тронут

JSON.parse(JSON.stringify(x)) — старый хак; теряет Date, Map, undefined, функции. Используйте structuredClone.

Object.freeze

Object.freeze(obj) блокирует изменения (только первый уровень). Полезно для констант конфигурации, чтобы ловить случайные мутации.

Коротко

  • Примитивы копируются по значению, объекты — по ссылке.
  • Иммутабельно = создать новый объект вместо изменения; обязательно для состояния в React.
  • Spread копирует только первый уровень; structuredClone — для полной копии.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.