Как сделать поверхностную копию объекта?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Поверхностная копия объекта в JavaScript
Поверхностная копия (shallow copy) — это новый объект, который содержит ссылки на те же значения, что и исходный объект. Это отличается от глубокой копии, где копируются и вложенные объекты.
Разница: поверхностная vs глубокая копия
const original = {
name: 'Иван',
address: { city: 'Москва', zip: '101000' }
};
// Поверхностная копия
const shallow = { ...original };
shallow.address.city = 'Спб';
console.log(original.address.city); // 'Спб' — исходный объект изменился!
// Глубокая копия
const deep = JSON.parse(JSON.stringify(original));
deep.address.city = 'Казань';
console.log(original.address.city); // 'Спб' — исходный объект не изменился
Способ 1: Spread оператор (...)
Это самый современный и популярный способ:
const user = { id: 1, name: 'Анна', active: true };
const userCopy = { ...user };
userCopy.name = 'Мария';
console.log(user.name); // 'Анна' — исходный не изменился
console.log(user === userCopy); // false — разные объекты
Плюсы:
- Чистый и понятный синтаксис
- Легко комбинировать с новыми свойствами
- Работает с массивами:
const arr2 = [...arr1]
const updated = { ...user, name: 'Наташа', age: 25 };
// { id: 1, name: 'Наташа', active: true, age: 25 }
Способ 2: Object.assign()
Традиционный метод копирования объектов:
const user = { id: 1, name: 'Боб' };
const userCopy = Object.assign({}, user);
// Или копирование свойств в существующий объект
const target = { role: 'admin' };
Object.assign(target, user);
console.log(target); // { role: 'admin', id: 1, name: 'Боб' }
Особенности:
- Первый параметр — целевой объект (изменяется)
- Возвращает целевой объект
- Копирует перечислимые свойства
const defaults = { theme: 'light', lang: 'ru' };
const userPrefs = { theme: 'dark' };
const config = Object.assign({}, defaults, userPrefs);
console.log(config); // { theme: 'dark', lang: 'ru' }
Способ 3: Object.create() с Object.getOwnPropertyNames()
Для более сложных случаев с дескрипторами свойств:
function shallowCopy(obj) {
const copy = Object.create(Object.getPrototypeOf(obj));
Object.getOwnPropertyNames(obj).forEach(prop => {
copy[prop] = obj[prop];
});
return copy;
}
const original = { x: 1, y: 2 };
const copy = shallowCopy(original);
Способ 4: Деструктуризация объекта
Для объектов с известной структурой:
const user = { name: 'Ольга', email: 'olga@example.com', age: 28 };
const { name, email, age } = user;
const userCopy = { name, email, age };
// Или с остатком
const { name, ...rest } = user;
const userWithoutName = rest; // { email: '...', age: 28 }
Способ 5: Array.slice() для массивов
Для массивов (поверхностная копия):
const original = [1, 2, 3];
const copy1 = original.slice();
const copy2 = [...original];
original.push(4);
console.log(copy1); // [1, 2, 3] — не изменилась
console.log(copy2); // [1, 2, 3] — не изменилась
Проблема с вложенными объектами
Поверхностная копия не копирует вложенные объекты и массивы:
const user = {
name: 'Владимир',
hobbies: ['чтение', 'спорт'],
address: { city: 'Москва' }
};
const copy = { ...user };
copy.hobbies.push('путешествия');
copy.address.city = 'Казань';
console.log(user.hobbies); // ['чтение', 'спорт', 'путешествия'] — изменилась!
console.log(user.address.city); // 'Казань' — изменилась!
Для решения нужна глубокая копия:
// JSON способ (простой, но с ограничениями)
const deepCopy = JSON.parse(JSON.stringify(user));
// Рекурсивная функция
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (Array.isArray(obj)) return obj.map(deepClone);
const copy = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepClone(obj[key]);
}
}
return copy;
}
Рекомендация
Для большинства случаев используй spread оператор ({ ...obj }) — это современный стандарт. Для глубокого копирования сложных структур используй библиотеки типа Lodash (_.cloneDeep()) или встроенный structuredClone() (новый API).