Gernar
JavaScript: язык и типы

Как скопировать объект в 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-элементы. Лучше использовать его в современных браузерах для надежного глубокого копирования.

Содержание