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

Как скопировать один объект в другой в JavaScript?

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

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

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

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

Методы копирования объектов в JavaScript

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

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

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

1. Spread оператор (ES6+)

const original = { a: 1, b: { nested: 2 } };
const copy = { ...original };

copy.a = 100; // Не влияет на original
copy.b.nested = 200; // Меняет original.b.nested!

2. Object.assign()

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

3. Цикл for...in

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

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

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

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

const original = { 
    name: "Test", 
    data: { value: 42 },
    date: new Date() // Будет преобразовано в строку
};

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

// Ограничения:
// - Игнорирует функции, undefined, Symbol
// - Преобразует Date в строку
// - Теряет прототипы

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

function deepClone(obj, hash = new WeakMap()) {
    // Обработка примитивов и null
    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 = Object.create(Object.getPrototypeOf(obj));
    hash.set(obj, clone);
    
    // Рекурсивное копирование свойств
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepClone(obj[key], hash);
        }
    }
    
    return clone;
}

3. structuredClone() (современный API)

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

const deepCopy = structuredClone(original);

// Преимущества:
// - Копирует большинство типов данных
// - Обрабатывает циклические ссылки
// - Поддерживает Map, Set, ArrayBuffer и др.
// Ограничения:
// - Не копирует функции, DOM-узлы
// - Не поддерживает прототипы

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

Когда использовать поверхностное копирование:

  • Объект не содержит вложенных объектов
  • Вложенные объекты являются иммутабельными
  • Требуется высокая производительность

Когда необходимо глубокое копирование:

  • Объект содержит изменяемые вложенные объекты
  • Требуется полная изоляция данных
  • Работа с состоянием в Redux/Vuex

Практические рекомендации

  1. Для простых объектов без методов используйте structuredClone() или JSON.parse(JSON.stringify())
  2. Для объектов с функциями и прототипами нужна кастомная реализация
  3. Всегда учитывайте циклические ссылки во избежание бесконечной рекурсии
  4. Тестируйте производительность — глубокое копирование тяжёлых объектов может быть дорогим
  5. Рассмотрите иммутабельные структуры данных (например, через библиотеки типа Immer.js)
// Пример с библиотекой Immer для иммутабельных обновлений
import { produce } from 'immer';

const original = { a: 1, b: { c: 2 } };
const copy = produce(original, draft => {
    draft.b.c = 3; // Безопасное изменение
});

Выбор метода зависит от структуры данных, требований к производительности и поддерживаемых типов. В современном JavaScript structuredClone() становится стандартом для большинства случаев глубокого копирования, но важно понимать его ограничения и альтернативы для специфических сценариев.

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

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

Копирование объектов в JavaScript

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

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

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

Способы поверхностного копирования:

  1. Spread оператор (...)

    const original = { a: 1, b: { inner: 2 } };
    const copy = { ...original };
    
  2. Метод Object.assign()

    const copy = Object.assign({}, original);
    
  3. Цикл for...in

    const copy = {};
    for (let key in original) {
        if (original.hasOwnProperty(key)) {
            copy[key] = original[key];
        }
    }
    

Важное ограничение:

const original = { a: 1, b: { inner: 2 } };
const shallowCopy = { ...original };

shallowCopy.a = 100; // Изменяется только копия
console.log(original.a); // 1 - оригинал не изменился

shallowCopy.b.inner = 200; // Проблема: изменяются оба объекта!
console.log(original.b.inner); // 200 - оригинал тоже изменился

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

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

Основные подходы:

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

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

    Недостатки:

    • Теряются функции, undefined, Symbol
    • Не копируются Map, Set, Date (превращаются в строки)
    • Не работают циклические ссылки
  2. Рекурсивная функция

    function deepClone(obj, hash = new WeakMap()) {
        // Обработка примитивов и null
        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 = Object.create(Object.getPrototypeOf(obj));
        hash.set(obj, clone);
        
        // Рекурсивное копирование свойств
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                clone[key] = deepClone(obj[key], hash);
            }
        }
        
        return clone;
    }
    
  3. Современный метод structuredClone()

    const deepCopy = structuredClone(original);
    

    Преимущества:

    • Поддерживает циклические ссылки
    • Сохраняет типы данных (Date, Map, Set, ArrayBuffer и др.)
    • Доступен в современных браузерах и Node.js (с версии 17)

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

МетодГлубинаФункцииЦиклыПроизводительность
Spread операторПоверхностнаяСохраняетНетВысокая
Object.assign()ПоверхностнаяСохраняетНетВысокая
JSON.parse/stringifyГлубокаяТеряетНетСредняя
structuredClone()ГлубокаяТеряетДаСредняя
Рекурсивная функцияГлубокаяНастраиваемаяДаНизкая

Практические рекомендации

Когда что использовать:

  • Поверхностное копирование — когда объект плоский или вложенные объекты не нужно изменять
  • structuredClone() — для большинства случаев глубокого копирования в современных приложениях
  • Кастомная рекурсивная функция — когда нужен полный контроль над процессом копирования
  • JSON методы — для простых данных без функций и специальных типов

Пример с structuredClone():

const complexObject = {
    date: new Date(),
    map: new Map([['key', 'value']]),
    set: new Set([1, 2, 3]),
    array: [1, 2, { nested: true }],
    nested: { level: 2 }
};

const cloned = structuredClone(complexObject);
cloned.map.set('newKey', 'newValue'); // Не влияет на оригинал
console.log(complexObject.map.get('newKey')); // undefined

Важное предупреждение: Все методы глубокого копирования могут быть ресурсоёмкими для больших объектов. Для работы с часто изменяемыми большими структурами данных рассмотрите использование иммутабельных структур (как в Redux) или библиотек типа Immer.

Выбор метода зависит от конкретного случая: структуры данных, требований к производительности и среды выполнения. В современных проектах structuredClone() часто является оптимальным выбором для глубокого копирования.

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

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

Как скопировать один объект в другой в JavaScript

Копирование объектов в JavaScript — нетривиальная задача, поскольку объекты передаются по ссылке, а не по значению. Простое присваивание obj2 = obj1 создаёт лишь новую ссылку на тот же объект, а не независимую копию. Разберем методы копирования с учетом глубины и производительности.

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

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

Методы поверхностного копирования:

  1. Spread оператор (ES6+):
const original = { a: 1, b: { nested: 2 } };
const copy = { ...original };
copy.a = 10; // Не влияет на original
copy.b.nested = 20; // Меняет original.b.nested!
  1. Object.assign():
const copy = Object.assign({}, original);
// Аналогично spread: вложенные объекты копируются по ссылке
  1. Цикл for...in:
const copy = {};
for (let key in original) {
    if (original.hasOwnProperty(key)) {
        copy[key] = original[key];
    }
}
  1. Object.fromEntries() с Object.entries():
const copy = Object.fromEntries(Object.entries(original));

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

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

Методы глубокого копирования:

  1. JSON.parse(JSON.stringify()):
const deepCopy = JSON.parse(JSON.stringify(original));

⚠️ Ограничения:

  • Игнорирует undefined, Symbol, функции
  • Преобразует Date в строки
  • Не работает с циклическими ссылками
  1. Рекурсивная функция:
function deepClone(obj) {
    if (obj === null || typeof obj !== 'object') return obj;
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof Array) return obj.map(deepClone);
    
    const clone = {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = deepClone(obj[key]);
        }
    }
    return clone;
}
  1. Использование библиотек:
  • Lodash: _.cloneDeep(obj)
  • Structured Clone API (современный браузерный/Node.js)

Structured Clone Algorithm

Современный стандартный API для глубокого копирования:

// В браузерах и Node.js
const deepCopy = structuredClone(original);

Преимущества:

  • Обрабатывает циклические ссылки
  • Копирует типизированные массивы, Map, Set, Date
  • Стандартизированная производительная реализация

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

МетодТип копированияПоддерживает функцииЦиклические ссылкиПроизводительность
Spread операторПоверхностныйДаДаВысокая
Object.assign()ПоверхностныйДаДаВысокая
JSON методыГлубокийНетНетСредняя
Рекурсивная реализацияГлубокийДаНет*Низкая
structuredClone()ГлубокийНетДаВысокая

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

  1. Для простых объектов без вложенности — используйте spread оператор: он лаконичен и производителен.
  2. Для полного глубокого копирования — предпочитайте structuredClone() где доступен, либо библиотечные решения.
  3. При работе с классами и методами — потребуется рекурсивная реализация или библиотека Lodash.
  4. Для копирования с преобразованиями — комбинируйте методы, например, spread с рекурсивной обработкой вложенных структур.

Пример комбинированного подхода

function smartClone(obj, depth = 1) {
    if (depth === 0) return { ...obj };
    
    const clone = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            clone[key] = (typeof obj[key] === 'object' && obj[key] !== null)
                ? smartClone(obj[key], depth - 1)
                : obj[key];
        }
    }
    return clone;
}

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

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

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

Копирование объектов в JavaScript

Копирование объектов в JavaScript — нетривиальная задача, поскольку объекты передаются по ссылке, а не по значению. Простое присваивание obj2 = obj1 создаст новую ссылку на тот же объект, а не независимую копию. Рассмотрим основные подходы.

1. Поверхностное копирование (Shallow Copy)

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

Методы:

  • Spread оператор (...):
const original = { a: 1, b: { c: 2 } };
const copy = { ...original };
copy.a = 10;       // Не влияет на original
copy.b.c = 20;     // Меняет original.b.c!
  • Object.assign():
const copy = Object.assign({}, original);
  • Цикл for...in:
function shallowCopy(obj) {
  const result = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      result[key] = obj[key];
    }
  }
  return result;
}

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

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

Методы:

  • JSON.parse(JSON.stringify()) (наиболее распространённый):
const deepCopy = JSON.parse(JSON.stringify(original));

⚠️ Ограничения:

  • Теряет функции, undefined, Symbol
  • Преобразует Date в строки
  • Не работает с циклическими ссылками
  • Игнорирует специальные объекты (Map, Set, RegExp и т.д.)
  • Рекурсивная функция:
function deepClone(obj, hash = new WeakMap()) {
  // Обработка примитивов и null
  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 = new obj.constructor();
  hash.set(obj, clone);
  
  // Рекурсивное копирование свойств
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], hash);
    }
  }
  
  return clone;
}
  • Встроенные возможности:
    • structuredClone() (современный стандарт):
    const copy = structuredClone(original);
    
    Поддерживает большинство типов, включая циклические ссылки, но не копирует функции, DOM-узлы и некоторые другие специфические объекты.

3. Библиотечные решения

  • Lodash:
const shallowCopy = _.clone(original);
const deepCopy = _.cloneDeep(original);
  • jQuery:
const shallowCopy = $.extend({}, original);
const deepCopy = $.extend(true, {}, original);

Критерии выбора метода

  1. Производительность: spread и Object.assign() быстрее всего
  2. Глубина копирования: определяет нужен ли shallow или deep clone
  3. Типы данных: JSON методы теряют функции и специальные объекты
  4. Браузерная поддержка: structuredClone() доступен не во всех старых браузерах
  5. Циклические ссылки: требуют специальной обработки
  6. Прототипная цепочка: должна сохраняться или нет

Практические рекомендации

  • Для простых объектов без вложенности используйте spread оператор
  • Для глубокого копирования в современных приложениях используйте structuredClone()
  • При работе с React/Redux состояниями часто достаточно поверхностного копирования с обновлением ссылок
  • Для сложных случаев с циклическими ссылками и специальными объектами реализуйте кастомную функцию или используйте Lodash

Выбор метода зависит от конкретной задачи. Всегда тестируйте, что именно копируется в вашем случае, особенно при работе с классами, методами и сложными структурами данных.