DevGang
Авторизоваться

Правильный способ клонирования JavaScript-объектов

Клонирование JS-объекта - довольно распространенная задача в нашей повседневной жизни. Обсудим методы ее решения.

PS. Для правильного клонирования используйте structuredClone, так как теперь он доступен в родном JS.

Неглубокое и глубокое клонирование

Сначала обсудим, что такое поверхностное клонирование и глубокое клонирование:

Неглубокое и глубокое клонирование - это два различных подхода к копированию объектов в JavaScript, которые имеют разные характеристики и случаи использования:

Неглубокое клонирование:

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

Глубокое клонирование:

При глубоком клонировании создается совершенно новый объект со всеми его свойствами и дублированием вложенных свойств. При этом обеспечивается отсутствие общих ссылок между исходным и клонированным объектами, в результате чего создается полностью независимая копия.

Неглубокое клонирование

1. Object.assign()

Метод Object.assign() - это лаконичный способ неглубокого клонирования объектов JavaScript. Он создает новый объект и копирует перечисляемые свойства из исходного объекта в новый. Однако следует помнить, что если свойства исходного объекта являются объектами или массивами, то они будут скопированы по ссылке.

const clonedObject = Object.assign({}, originalObject);

2. Оператор spread (ES6)

Оператор spread - это еще один метод неглубокого клонирования объектов, появившийся в ES6. Он предоставляет более современный и лаконичный синтаксис для создания неглубокой копии объекта.

const clonedObject = { ...originalObject };

Глубокое клонирование

3. JSON.parse() and JSON.stringify()

Для создания глубокого клона объекта можно использовать JSON.parse() и JSON.stringify(). Этот метод сериализует исходный объект в строку JSON, а затем разбирает ее и создает новый объект. Он отлично подходит для глубокого клонирования, но имеет свои ограничения, например, не работает с функциями, символами и круговыми ссылками.

const clonedObject = JSON.parse(JSON.stringify(originalObject));

4. Структурированный клон

В средах веб-рабочих для клонирования объектов можно использовать метод structuredClone. Этот метод может работать с более сложными типами данных, но он специфичен для веб-работников.

Сравнение методов глубокого клонирования

Допустим, у вас есть объект со свойством функции:

const originalObject = {
  name: "John",
  age: 30,
  greet: function () {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  },
};

Теперь попробуем клонировать этот объект, используя оба метода: JSON.parse(JSON.stringify()) и structuredClone.

1. Используем JSON.parse(JSON.stringify()):

const cloneWithJSON = JSON.parse(JSON.stringify(originalObject));

// Attempt to call the function in the cloned object
cloneWithJSON.greet(); // Throws an error: cloneWithJSON.greet is not a function

Как видно, свойство функции теряется в процессе клонирования. JSON.stringify сериализует объект в JSON, а JSON.parse создает новый объект из JSON-представления. Функции не являются валидным JSON, поэтому они опускаются.

2. Используем structuredClone:

const clonedObject = structuredClone(originalObject);

// Attempt to call the function in the cloned object
clonedObject.greet(); // Works as expected: "Hello, my name is John and I am 30 years old."

При использовании structuredClone в процессе клонирования сохраняется свойство функции, и ее можно без проблем вызывать на клонированном объекте. Этот метод является более мощным и универсальным при работе со сложными объектами, содержащими несериализуемые свойства.

Заключение

  • Для неглубокого клонирования следует использовать оператор spread или Object.assign() из-за их простоты.
  • Если требуется глубокое клонирование, а объект не содержит функций, символов или циклических ссылок, используйте JSON.parse() и JSON.stringify().
  • Лучше всего использовать метод structuredClone, поскольку он теперь доступен нативно и позволяет клонировать даты, RegExps, карты, наборы, блобы, списки файлов, ImageDatas, разреженные массивы, типизированные массивы.

Спасибо за прочтение!

Источник:

#JavaScript #NodeJS #React
Комментарии 1
Алексей Ярков 08.12.2024 в 12:08

Ну и зачем это враньё про функцию (метод) объекта. Получим ошибку: Uncaught DataCloneError: Failed to execute 'structuredClone' on 'Window'

Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу