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

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

Поверхностное клонирование

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

Объект.назначить

Метод Object.assign — это простой способ создать поверхностную копию объекта. Он берет один или несколько исходных объектов и копирует их свойства в целевой объект. Вот пример:

const originalObject = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Anytown",
    state: "CA"
  }
};

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

clonedObject.address.street = "456 Second St";

console.log(originalObject.address.street); // Output: 456 Second St
console.log(clonedObject.address.street); // Output: 456 Second St

В этом примере у нас есть объект originalObject с вложенным объектом address. Мы используем Object.assign({}, originalObject) для создания поверхностного клона originalObject и назначаем его clonedObject. Затем мы изменяем свойство street вложенного объекта address в clonedObject. Наконец, мы регистрируем свойство street как originalObject, так и clonedObject в консоли.

Как и ожидалось, изменение свойства street элемента clonedObject влияет на свойство street элемента originalObject.

Оператор спреда

Оператор распространения также можно использовать для создания поверхностной копии объекта. Он работает, распространяя свойства объекта на новый объект. Вот пример:

const originalObject = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Anytown",
    state: "CA"
  }
};

const clonedObject = { ...originalObject };

clonedObject.address.street = "456 Second St";

console.log(originalObject.address.street); // Output: 456 Second St
console.log(clonedObject.address.street); // Output: 456 Second St

В этом примере мы используем оператор распространения { ...originalObject }, чтобы создать неглубокий клон originalObject и назначить его clonedObject. Затем мы изменяем свойство street вложенного объекта address в clonedObject. Наконец, мы записываем в консоль свойство street как originalObject, так и clonedObject.

Как и ожидалось, изменение свойства street элемента clonedObject влияет на свойство street элемента originalObject.

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

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

JSON.parse(JSON.stringify(obj))

Еще один распространенный метод клонирования объектов в JavaScript — JSON.parse(JSON.stringify(obj)). Этот метод сериализует объект в JSON, а затем анализирует его обратно в новый объект. Хотя это может создать глубокий клон объекта, у него есть ограничения, когда дело доходит до обработки определенных типов данных, таких как функции и неопределенные значения. Кроме того, этот метод может быть медленнее и менее эффективен, чем другие методы, особенно при работе с большими и сложными объектами. Вот пример:

const originalObject = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Anytown",
    state: "CA"
  }
};

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

clonedObject.address.street = "456 Second St";

console.log(originalObject.address.street); // Output: 123 Main St
console.log(clonedObject.address.street); // Output: 456 Second St

В этом примере мы используем JSON.parse(JSON.stringify(originalObject)) для создания глубокого клона originalObject и назначаем его clonedObject. Затем мы изменяем свойство street вложенного объекта address в clonedObject. Наконец, мы записываем в консоль свойство street как originalObject, так и clonedObject.

Как и ожидалось, изменение свойства street элемента clonedObject не влияет на свойство street элемента originalObject.

структурированный клон

Метод structuredClone — это новое дополнение к JavaScript, позволяющее эффективно и полностью клонировать объекты, включая сложные объекты, такие как функции, даты, регулярные выражения и т. д. Этот метод доступен только в определенных средах, таких как службы и веб-воркеры. Вот пример:

const originalObject = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Anytown",
    state: "CA"
  }
};

const clonedObject = structuredClone(originalObject);

clonedObject.address.street = "456 Second St";

console.log(originalObject.address.street); // Output: 123 Main St
console.log(clonedObject.address.street); // Output: 456 Second St

В этом примере мы используем метод structuredClone, чтобы создать глубокий клон originalObject и назначить его clonedObject. Затем мы изменяем свойство street вложенного объекта address в clonedObject. Наконец, мы записываем в консоль свойство street как originalObject, так и clonedObject.

Как и ожидалось, изменение свойства street элемента clonedObject не влияет на свойство street элемента originalObject.

Заключение

Клонирование объектов в JavaScript — важный метод предотвращения неожиданного поведения и сохранения целостности данных. Поверхностное клонирование — это простой способ создания копии объекта, но у него есть ограничения, когда речь идет о вложенных объектах и ​​изменяемых свойствах. Глубокое клонирование — более полное решение, но оно может быть медленнее и менее эффективно, особенно для больших и сложных объектов. structuredClone — это более новый метод, который обеспечивает полное и эффективное клонирование объектов, но он доступен только в определенных средах. Выберите метод, который лучше всего соответствует вашим потребностям, исходя из сложности ваших объектов и требований к производительности вашего приложения.

Дальнейшее чтение

Если вы хотите узнать больше о клонировании объектов в JavaScript, вот некоторые ресурсы, которые стоит проверить:

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