2022-08-13 14:35:13
Поверхностное и глубокое клонирование объектов в 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
807 views11:35