Способы объединить объекты в JS (JavaScript)

Как объединить объекты в JS (JavaScript)

03.02.2024
225
6 мин.
0

Разработчики часто сталкиваются с такими задачами, как объединить объекты в JS (JavaScript) для различных задач. В этом случае важными инструментами являются оператор spread(…) и метод Object.assign(). Однако понимание того, когда и как их использовать, имеет решающее значение для эффективного манипулирования объектами. В этой статье мы рассмотрим их некоторые практические применения, сильные и слабые стороны, а также концепции глубокого копирования перед объединением вложенных объектов.

Способы объединения объектов

Как объединить объекты в JS оператором spread(…)

Это распространённый подход к объединению 2 и более объектов в JavaScript. Он имеет вид {…object1, …object2}. Если свойства с одинаковыми ключами присутствуют в исходных объектах, spread оператор перезаписывает значения в целевом объекте последними значениями исходного. Например:

const defaults = { color: 'red', size: 'medium' };
const userSettings = { color: 'blue' };

const combinedSettings = { ...defaults, ...userSettings };
console.log(combinedSettings);
// Результат: { color: 'blue', size: 'medium' }

Как объединить объекты в JS методом Object.assign()

Это метод JavaScript для объединения объектов. Его синтаксис —Object.assign(target, source1, source2, …). Таким способом происходит объединение исходных объектов в целевой объект. При наличии свойств с одинаковыми ключами в исходных объектах, Object.assign() перезаписывает значения в целевом объекте последними значениями исходного объекта.

const defaults = { color: 'red', size: 'medium' };
const userSettings = { color: 'blue' };

const combinedSettings = Object.assign({}, defaults, userSettings);
console.log(combinedSettings);
// Результат: { color: 'blue', size: 'medium' }

Подводные камни и сравнение обоих способов

Ниже перечислены потенциальные проблемы, связанные как со spread оператором, так и с методом Object.assign(), когда необходимо объединить объекты в JS.

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

Как оператор spread(), так и Object.assign() выполняют неглубокое копирование при объединении объектов. Это означает, что вложенные объекты по-прежнему являются ссылками на исходные. Изменение вложенных объектов в объединённом объекте может повлиять на исходные объекты, что может привести к непреднамеренным побочным эффектам.

Кроссбраузерность

Оператор spread является частью ECMAScript 2015 (ES6) и не поддерживается в старых браузерах, таких как Internet Explorer. Если это важно, то в таких случаях лучше использовать Object.assign(), который имеет более широкую поддержку.

Неперечисляемые свойства

В частности, как оператор spread(), так и Object.assign() копируют только перечислимые свойства из исходных объектов в целевой объект. Неперечисляемые свойства не копируются в процессе слияния, что может привести к отсутствию части данных или неожиданному результату.

Как объединить объекты в JS и избежать проблем с производительностью

Способы объединить объекты в JS (JavaScript)
Как выбрать лучший способ объединения объектов в JavaScript (изображение создано с помощью ИИ)

В случаях, когда вам необходимо объединить большие объекты или часто выполнять операции слияния, использование Object.assign() или оператора spread() может вызвать проблемы с производительностью из-за создания новых объектов в процессе слияния.

Свойства прототипа

Object.assign() копирует свойства из прототипа исходного объекта в целевой, что может привести к неожиданному поведению. Это возможно, если прототип исходного объекта имеет свойства, противоречащие свойствам целевого объекта. Оператор spread(), с другой стороны, не копирует свойства прототипа.

Важно знать об этих подводных камнях и проблемах при использовании оператора spread() или Object.assign(), чтобы объединить объекты в JS. В определённых случаях может потребоваться использовать альтернативные подходы. Речь идёт о глубоком клонировании или функции глубокого слияния, которые позволяют преодолеть эти ограничения.

Какой метод использовать

Стоит отметить, что и Object.assign(), и оператор spread() эффективно объединяют объекты. Второй более лаконичен и современен, в то время как первый обеспечивает хорошую кроссбраузерность.

Чтобы решить, какой метод лучше использовать, следует учитывать:

  • если ваша среда поддерживает оператор spread() (например, последняя версия ECMAScript), используйте его из-за его краткого синтаксиса;
  • если важна совместимость со старыми браузерами, выберите Object.assign();
  • если вам нужно скопировать вложенный объект (объект с вложенными в него объектами), следует прибегнуть к глубокому копированию объекту.

Глубокое копирование и слияние объектов

Как оператор spread(), так и Object.assign() создают неглубокую копию копируемого объекта или объектов. По сути, это означает, что новый объект будет иметь ссылки на вложенные объекты (например, массивы и функции), что и исходный объект. Вместо создания их копии. Важно знать об этом и избегать этого перед объединением объектов.

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

const planet = {
  name: 'Earth',
  emoji: '🌍',
  info: {
    type: 'terrestrial',
    moons: 1
  }
};

// Копирование с использованием оператора распространения
const shallowCopyPlanet = { ...planet };

// Изменение вложенного объекта в копии
shallowCopyPlanet.info.moons = 2;

console.log('Original planet:', planet.info.moons);
// Значение свойства в оригинале planet: 2
console.log('Shallow copy of the planet:', shallowCopyPlanet.info.moons);
// Значение свойства в копии planet: 2

Выходные данные этого кода показывают, что свойство info.moons в исходном объекте planet было изменено путём редактирования его в shallowCopyPlanet, чего по условиям задачи, например, не требуется.

Читайте также: Конкатенация строк в JavaScript.

Пользовательская функция глубокого копирования

Ниже представлена функция, которая глубоко копирует несколько объектов перед их объединением. Её результатом является один новый объект. Функция deepMergeObjects принимает любое количество входных объектов. Она создаёт их глубокие копии, используя метод JSON.parse(JSON.stringify()). Затем объединяет их, используя оператор spread() внутри метода reduce(). Объединённый объект будет содержать глубокие копии свойств из исходных объектов. Например:

const deepMergeObjects = (...objects) => {
  const deepCopyObjects = objects.map(object => JSON.parse(JSON.stringify(object)));
  return deepCopyObjects.reduce((merged, current) => ({ ...merged, ...current }), {});
}

// Example usage:
const countries = {
  USA: {
    capital: 'Washington D.C.',
    emoji: '🇺🇸',
    population: 331000000
  }
};

const countriesDetails = {
  USA: {
    language: 'English',
    currency: 'USD'
  },
  Germany: {
    capital: 'Berlin',
    emoji: '🇩🇪',
    language: 'German',
    currency: 'EUR',
    population: 83000000
  }
};

const mergedData = deepMergeObjects(countries, countriesDetails);