← Назад к вопросам

Как создать клон объекта?

2.0 Middle🔥 152 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Методы создания клона объекта в JavaScript

Клонирование объектов — важная задача, поскольку присваивание по ссылке в JavaScript приводит к тому, что изменения в «копии» влияют на оригинал. Существует несколько подходов, каждый со своими особенностями.

📌 Поверхностное клонирование (Shallow Copy)

Создаёт новый объект, но вложенные объекты/массивы копируются по ссылке.

1. Spread оператор (...) (современный стандарт)

const original = { a: 1, b: { c: 2 } };
const clone = { ...original };

console.log(clone.a); // 1
console.log(clone.b === original.b); // true (вложенный объект — ссылка)

2. Object.assign()

const original = { x: 10, y: { z: 20 } };
const clone = Object.assign({}, original);

3. Цикл for...in

function shallowClone(obj) {
  const clone = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = obj[key];
    }
  }
  return clone;
}

📌 Глубокое клонирование (Deep Copy)

Полностью независимая копия со всеми вложенными структурами.

1. JSON методы (ограниченный способ)

const original = { 
  name: "Test", 
  data: { values: [1, 2, 3] },
  date: new Date()
};

const clone = JSON.parse(JSON.stringify(original));

console.log(clone.data !== original.data); // true
console.log(typeof clone.date); // "string" (дата стала строкой!)

Недостатки: теряются функции, undefined, Symbol, Map/Set, классовые инстансы, циклические ссылки вызывают ошибку.

2. Рекурсивная функция

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (hash.has(obj)) return hash.get(obj);
  
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  
  const clone = Array.isArray(obj) ? [] : {};
  hash.set(obj, clone);
  
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], hash);
    }
  }
  
  // Для Symbol ключей
  const symbolKeys = Object.getOwnPropertySymbols(obj);
  for (let symKey of symbolKeys) {
    clone[symKey] = deepClone(obj[symKey], hash);
  }
  
  return clone;
}

3. Использование structuredClone() (современный API)

const original = {
  name: "Object",
  nested: { array: [1, 2, 3] },
  date: new Date()
};

const clone = structuredClone(original);

console.log(clone.nested !== original.nested); // true
console.log(clone.date instanceof Date); // true

Преимущества: поддерживает больше типов данных, обрабатывает циклические ссылки, но не клонирует функции, DOM-узлы, прототипы.

📌 Специализированные библиотеки

  • Lodash: _.cloneDeep(value)
  • jQuery: $.extend(true, {}, original)

📋 Сравнение методов

МетодГлубинаФункцииЦиклические ссылкиПроизводительность
Spread операторПоверхностнаяСохраняетНеприменимоВысокая
JSON методыГлубокаяТеряетОшибкаСредняя
РекурсияГлубокаяСохраняетОбрабатываетЗависит от глубины
structuredClone()ГлубокаяТеряетОбрабатываетВысокая

🎯 Рекомендации по выбору

  1. Для простых объектов без вложенностей — используйте spread или Object.assign()
  2. Для полного глубокого клонирования — предпочтительнее structuredClone() в поддерживаемых средах
  3. Для сложных случаев с функциями/классами — пишите кастомную рекурсивную функцию или используйте проверенную библиотеку
  4. Всегда проверяйте наличие циклических ссылок в данных

Ключевой принцип: выбирайте метод в зависимости от структуры данных и требований к производительности. Для большинства повседневных задач structuredClone() и spread оператора достаточно, но важно понимать их ограничения, особенно при работе с state management (Redux, MobX) или immutable подходами.

Как создать клон объекта? | PrepBro