Объекты: копирование, сравнение, дескрипторы
↑ 1.4 JavaScript: основы · ← Предыдущая · → Следующая
Зачем это на собесе
Разница поверхностного и глубокого копирования и работа с дескрипторами свойств.
Объяснение
Объекты присваиваются и передаются по ссылке.
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).
Практика
- Реализуйте
deepCloneс обработкой циклических ссылок. - Создайте неизменяемое свойство через
defineProperty. - Сравните способы копирования на сложном объекте.
Вопросы с ответами
Как глубоко скопировать объект?
structuredClone(илиlodash.cloneDeep); JSON подходит только для простых данных.
Что делает
enumerable: false?Свойство скрывается из перебора (
for...in,Object.keys, spread).