Нам часто нужно копировать / клонировать объекты. JavaScript предлагает несколько решений этой проблемы. В этой статье мы сравним некоторые из них.
Object.assign
Метод
Давайте создадим объект человека и клонируем его с помощью Object.assign
в примере ниже:
const person = { name: 'john', age: 35, interests: { javascript: true } }; const clone = Object.assign({}, person); console.log(clone); // { name: 'john', age: 35, interests: { javascript: true } }
Печать значений из объекта клона показывает, что клон имеет те же свойства и значения, что и объект человека.
Object.assign
копирует свойства и их значения из второго аргумента (и последних аргументов, если они существуют) в первый аргумент (целевой объект) и возвращает первый аргумент. Поскольку в качестве целевого аргумента мы передали литерал пустого объекта, возвращаемое значение является неглубокой копией объекта person
.
Слово мелкий является здесь ключевым. Давайте добавим приведенный ниже код в наш пример и посмотрим, что произойдет, если мы изменим значения в исходном объекте person:
... person.name = 'jane'; person.age = 40; person.interests.javascript = false; console.log(person); // { name: 'jane', age: 40, interests: { javascript: false } } console.log(clone); // { name: 'john', age: 35, interests: { javascript: false } }
Измененные значения name
и age
в объекте-персонаже не повлияли на объект-клон. Однако interest
изменен на обоих объектах. Это ожидается?
Короткий ответ - да! При поверхностном клонировании значения всех свойств копируются с примитивными типами. Однако свойства Object и Array являются ссылками, и связанные объекты / массивы не будут скопированы в неглубокий клон. Вместо этого ссылки копируются. interest
- это вложенный объект внутри объекта person, и только ссылка на него копируется в clone. Оба объекта имеют ссылку на один и тот же объект interest
, поэтому изменение свойства интереса с помощью объекта person напрямую изменит интерес клонированного объекта и наоборот.
Чтобы решить эту проблему, необходимо выполнять глубокое клонирование вместо поверхностного клонирования. Глубокое клонирование не будет рассматриваться в этой статье, но это хороший кандидат для следующей.
Object.assign
- мощная функция, у которой много других применений, но давайте сосредоточимся на поверхностном клонировании и рассмотрим альтернативные методы.
Оператор распространения (синтаксис ...
) Метод
Оператор распространения поставляется со стандартом ECMAScript 2018 и теперь поддерживается большинством современных браузеров и NodeJS по умолчанию. Его использование довольно простое. Просто замените строку клонирования в приведенном выше примере на следующую:
const clone = { ...person };
Вот и все! Оператор распространения удобочитаем и элегантен. Он передает свойства объекта person в пустой литерал объекта.
Оператор распространения также очень мощный и имеет множество применений, таких как копирование, расширение, объединение объектов и массивов, распространение массивов в аргументы функций, деструктуризация массивов / объектов и многое другое. Подробнее об операторе распространения мы поговорим в другой статье.
Метод Лодаша
В большинстве случаев в наших приложениях рекомендуется использовать служебную библиотеку. Хотя JavaScript с годами становится все более и более мощным, его стандартный набор инструментов не покрывает все наши амбициозные требования. На этом этапе к действию присоединяются служебные библиотеки. Lodash - популярный выбор. Вот как это делается в _
:
const _ = require('lodash'); ... const clone = _.clone(person);
Опять же, читабельно и элегантно. Lodash также поддерживает глубокое клонирование "из коробки" своим cloneDeep
методом.
Заключение
Мы продемонстрировали 3 способа поверхностного клонирования:
Object.assign({}, person); // Old-school JS const clone = { ...person }; // Spread operator const clone = _.clone(person); // Lodash method
Какой метод вы предпочитаете? Вы используете другие альтернативы? Напишите, пожалуйста, в комментариях. Не забудьте поддержать вас аплодисментами и репостами, если вам понравилась статья. Удачного кодирования!