Объекты: копирование, сравнение, дескрипторы

↑ 1.4 JavaScript: основы · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: junior

Зачем это на собесе

Разница поверхностного и глубокого копирования и работа с дескрипторами свойств.

Объяснение

Объекты присваиваются и передаются по ссылке.

const a = { n: 1, nested: { x: 1 } };
const b = a;              b.n = 2;            // a.n тоже 2
const shallow = { ...a }; // или Object.assign({}, a) — поверхностная копия
shallow.nested.x = 9;     // a.nested.x тоже 9
const deep = structuredClone(a);   // глубокая копия (Date, Map, Set, циклы), но не функции
JSON.parse(JSON.stringify(a));     // теряет функции, undefined, Date → строка, Map/Set
СпособЧто копирует
Spread, Object.assignверхний уровень (shallow)
structuredCloneглубоко, встроенные типы
JSONтолько JSON-совместимое
lodash.cloneDeepглубоко, включая многие типы

Дескрипторы свойств:

const o = {};
Object.defineProperty(o, "id", { value: 1, writable: false, enumerable: false, configurable: false });
Object.getOwnPropertyDescriptor(o, "id");   // { value: 1, writable: false, ... }
Object.defineProperty(o, "full", { get() { return `${this.a} ${this.b}`; }, enumerable: true });
ФлагСмысл
writableможно менять значение
enumerableвидно в for...in, Object.keys, spread
configurableможно удалить/переопределить
get/setаксессоры

Иммутабельность: Object.freeze (неизменяемый, мелко), Object.seal (нельзя добавлять/удалять), Object.preventExtensions.

Полезное: Object.keys/values/entries, Object.fromEntries, in, hasOwn, оператор ?. и ??, деструктуризация с переименованием, вычисляемые ключи.

Нюансы и подводные камни

  • Spread копирует только собственные перечисляемые свойства и не копирует прототип.
  • JSON-копирование ломает Date, undefined, NaN, циклические ссылки.
  • Порядок ключей: целочисленные по возрастанию, затем строковые в порядке добавления.
  • Object.freeze не замораживает вложенные объекты.
  • Во Vue реактивные прокси: structuredClone работает только над «сырыми» данными (toRaw).

Практика

  1. Реализуйте deepClone с обработкой циклических ссылок.
  2. Создайте неизменяемое свойство через defineProperty.
  3. Сравните способы копирования на сложном объекте.

Вопросы с ответами

Связанные темы