Назад к вопросам
Middle
67
questionbank

Какими способами можно клонировать объект в JavaScript?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

  • Спред-оператор ... (Shallow Copy).
  • Object.assign() (Shallow Copy).
  • JSON.parse(JSON.stringify(obj)) (Deep Copy, но с ограничениями).
  • Рекурсивная функция (Deep Copy).
  • Библиотеки (например, Lodash с методом _.cloneDeep(), Deep Copy).

Сравнение Shallow vs. Deep Copy:

Тип клонирования Описание Пример
Shallow Copy Копирует поверхностные свойства. Вложенные объекты остаются по ссылке. const newObj = { ...origObj }; / const newObj = Object.assign({}, origObj);
Deep Copy Копирует все свойства, включая вложенные объекты и массивы. const newObj = JSON.parse(JSON.stringify(origObj)); / Функция глубокого копирования / _.cloneDeep(origObj)

Ограничения JSON.parse(JSON.stringify(obj)):

  • Не копирует функции.
  • Не копирует undefined.
  • Не копирует Symbol.
  • Не копирует циклические ссылки.
  • Преобразует Date объекты в строки.
  • Преобразует NaN, Infinity и -Infinity в null.

Пример shallow copy со спред-оператором:

const originalObj = {
  name: 'Alice',
  address: {
    city: 'New York',
    zip: '10001'
  }
};

const shallowCopy = { ...originalObj };

shallowCopy.name = 'Bob'; // Изменяется только копия
shallowCopy.address.city = 'Los Angeles'; // Изменяется и оригинал, и копия (вложенный объект по ссылке)

// console.log(originalObj.name); // Alice
// console.log(originalObj.address.city); // Los Angeles

Пример глубокого копирования с JSON.parse(JSON.stringify()):

const originalObj = {
  name: 'Alice',
  address: {
    city: 'New York'
  },
  greet: function() {
    console.log('Hello');
  },
  undefinedProp: undefined
};

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

deepCopy.name = 'Bob';
deepCopy.address.city = 'Los Angeles';

// console.log(originalObj.name); // Alice
// console.log(originalObj.address.city); // New York
// console.log(deepCopy.greet); // undefined (функция не скопировалась)
// console.log(deepCopy.undefinedProp); // undefined (undefined не скопировался)

Пример рекурсивной функции для глубокого копирования:

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj; // Базовый случай: примитивы или null
  }

  // Обработка Array
  if (obj instanceof Array) {
    const copy = [];
    for (let i = 0; i < obj.length; i++) {
      copy[i] = deepClone(obj[i]);
    }
    return copy;
  }

  // Обработка Object
  if (obj instanceof Object) {
    const copy = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        copy[key] = deepClone(obj[key]);
      }
    }
    return copy;
  }

  // Для других типов объектов, которые нам не нужны в сценарии клонирования
  throw new Error("Unable to copy obj! Its type isn't supported.");
}

const originalObj = {
  name: 'Alice',
  address: {
    city: 'New York'
  },
  numbers: [1, 2, { three: 3 }]
};

const deepCopy = deepClone(originalObj);

deepCopy.name = 'Bob';
deepCopy.address.city = 'Los Angeles';
deepCopy.numbers[2].three = 4;

// console.log(originalObj.name); // Alice
// console.log(originalObj.address.city); // New York
// console.log(originalObj.numbers[2].three); // 3