Как скопировать объект в JS
Разбор вопроса «Как скопировать объект в JS» для Frontend Developer: что проверяет интервьюер, ключевые тезисы, практические примеры и частые ошибки.
Вопрос
Как скопировать объект в JS
Профессия
Frontend Developer
Что хочет услышать интервьюер
Интервьюер хочет убедиться, что кандидат понимает разницу между поверхностным и глубоким копированием, знает основные методы для выполнения этих операций и может объяснить их ограничения. Также важно, чтобы кандидат упомянул альтернативные подходы, такие как использование библиотек или современных API.
Ключевые тезисы
- Поверхностное копирование можно выполнить с помощью оператора spread (например,
const newObj = {...oldObj}) или методаObject.assign(). - Для глубокого копирования объектов используется
JSON.parse(JSON.stringify(obj)), но этот метод не работает с функциями,undefinedи циклическими ссылками. - Более универсальный способ глубокого копирования — использование библиотек, таких как
lodash(метод_.cloneDeep). - Для копирования объектов с сохранением прототипов и методов можно использовать
structuredClone, который поддерживается в современных браузерах.
Подробный ответ
В JavaScript копирование объектов — важная тема, так как объекты передаются по ссылке. Поверхностное копирование создает новый объект, но вложенные объекты остаются ссылками. Для этого используют оператор spread ({...obj}) или Object.assign({}, obj). Однако эти методы не подходят для глубокого копирования, так как вложенные объекты остаются связанными. Для глубокого копирования часто применяют JSON.parse(JSON.stringify(obj)), но у этого метода есть ограничения: он не копирует функции, undefined, символы и циклические ссылки. Более надежные способы — использование библиотек (например, lodash.cloneDeep) или встроенного метода structuredClone, который поддерживается в современных браузерах и корректно обрабатывает циклические ссылки и сложные типы данных.
Практические примеры
Пример 1
Пример поверхностного копирования: `const original = { a: 1, b: { c: 2 } }; const copy = { ...original };`. Здесь `copy.b` ссылается на тот же объект, что и `original.b`.Пример 2
Пример глубокого копирования через `JSON.parse(JSON.stringify())`: `const deepCopy = JSON.parse(JSON.stringify(original));`. Этот метод не сработает, если в объекте есть функции или `undefined`.Пример 3
Пример использования `structuredClone`: `const cloned = structuredClone(original);`. Этот метод корректно копирует большинство типов данных, включая циклические ссылки.Частые ошибки
- Использование поверхностного копирования (
...илиObject.assign) для глубокого копирования, что приводит к изменению исходного объекта при изменении копии. - Попытка скопировать объект с функциями или
undefinedчерезJSON.parse(JSON.stringify()), что приводит к их потере.
Связанные темы
- Иммутабельность в JavaScript
- Работа с прототипами объектов
- Методы работы с объектами (
Object.keys,Object.values,Object.entries) - Библиотеки для работы с данными (Lodash, Ramda)
Follow-up вопросы
Какие ограничения у метода JSON.parse(JSON.stringify(obj)) для глубокого копирования?
Уровень: basic
Этот метод не работает с функциями, undefined, символами (Symbol), циклическими ссылками и объектами, которые не сериализуются в JSON (например, Date или Map).
Как скопировать объект с сохранением его прототипа?
Уровень: intermediate
Можно использовать Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)) или structuredClone (если прототип простой).
В чем разница между Object.assign() и оператором spread?
Уровень: basic
Оба выполняют поверхностное копирование, но Object.assign() изменяет первый переданный объект, а spread создает новый. Spread также удобнее для работы с вложенными структурами.
Как обработать циклические ссылки при глубоком копировании?
Уровень: advanced
Использовать библиотеки вроде lodash.cloneDeep (они обрабатывают циклические ссылки) или написать кастомную рекурсивную функцию с проверкой на циклические ссылки через WeakMap.
Когда стоит использовать structuredClone вместо других методов?
Уровень: intermediate
structuredClone подходит для копирования сложных объектов (включая вложенные массивы, Map, Set, Date), но не поддерживает функции и DOM-элементы. Лучше использовать его в современных браузерах для надежного глубокого копирования.
В чем разница между call и apply
Разбор вопроса «В чем разница между call и apply» для Frontend Developer: что проверяет интервьюер, ключевые тезисы, практические примеры и частые ошибки.
В чем разница между изменяемыми (мутабельными) и неизменяемыми (иммутабельными) типами данных
Разбор вопроса «В чем разница между изменяемыми (мутабельными) и неизменяемыми (иммутабельными) типами данных» для Frontend Developer: что проверяет интервьюер, ключевые тезисы, практические примеры и частые ошибки.