Получи случайную криптовалюту за регистрацию!

Поверхностное и глубокое клонирование объектов в JS Если у на | WebCoder | Frontend

Поверхностное и глубокое клонирование объектов в JS

Если у нас стоит задача скопировать простой объект и массив, то проблем не возникает, например:

simpleObj = {
fieldOne: 1,
fieldTwo: 2,
fieldThree: 3,
};

console.log(simpleObj);
// простой объект - {fieldOne: 1, fieldTwo: 2, fieldThree: 3,}

const simpleObjectCopy = {... simpleObj}; // используем spread для копирования простого объекта

console.log(simpleObjectCopy);
//клонированный простой объект - {fieldOne: 1, fieldTwo: 2, fieldThree: 3,}

simpleObjectCopy.fieldOne = 2; //изменим значение первого поля в копированном объекте, чтоб убедится что эти два объекта не связаны

console.log(simpleObj); // {fieldOne: 1, fieldTwo: 2, fieldThree: 3,}
console.log(simpleObjectCopy); // {fieldOne: 2, fieldTwo: 2, fieldThree: 3,}

Но что если у нас более сложный объект или массив (объект внутри которого другой объект или массив с объектами как в примере)

const foodInCart = [
{ product: 'Агава', quantity: 3},
{ product: 'Апельсин', quantity: 1 },
{ product: 'Дыня', quantity: 1 },
]

const clonedCart = [...foodInCart]

console.log(clonedCart);
// [
// { product: 'Агава', quantity: 3 },
// { product: 'Апельсин', quantity: 1 },
// { product: 'Дыня', quantity: 1 },
// ]

= 5 // изменяем поле "количество" в объекте под индексом 1

console.log(clonedCart)
// [
// { product: 'Агава', quantity: 3 },
// { product: 'Апельсин', quantity: 5 },
// { product: 'Дыня', quantity: 1 },
// ]

console.log(foodInCart)
// [
// { product: 'Агава', quantity: 3 },
// { product: 'Апельсин', quantity: 5 },
// { product: 'Дыня', quantity: 1 },
// ]

Как мы видим количество апельсинов поменялось сразу в двух объектах, как мы с вами знаем непримитивные типы данных, хранятся по ссылке. Так как мы произвели поверхностное копирование, то мы просто скопировали ссылки на старый объект в новый массив.

Таким образом, "разные" массивы ссылаются на одни и те же объекты в памяти:

=== clonedCart[1]); //true

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

Можно написать функцию глубокого копирования вручную. Скорее всего ваша функция будет рекурсивной, и она будет работать только для конкретных данных — написать универсальную функцию не так-то просто.

Так же можно сериализировать копируемый объект в JSON и распарсить его :

const deepClone = JSON.parse(JSON.stringify(foodInCart))

console.log(foodInCart[1] === deepClone[1]) // false

Но данный метод не идеальный, потому что копируемые данные должны быть сериализуемыми. Если у объекта существуют методы или массив содержит функции, то копирование не сработает.

Еще один способ это воспользоваться популярной библиотекой утилит lodash