Как объединить два объекта в JavaScript: 5 лучших методов

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему слияние объектов — это боль каждого JavaScript-разработчика

Представьте: вы работаете над приложением, и вам нужно объединить данные из двух разных источников. Например, у вас есть базовая конфигурация пользователя из базы данных и настройки, пришедшие с фронтенда. Как их соединить без боли и страданий? Именно этот вопрос — «How can I merge properties of two JavaScript objects?» — собрал тысячи просмотров на Stack Overflow. И не зря: слияние объектов в JavaScript таит в себе множество подводных камней.

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

Проблема: что значит «объединить свойства двух объектов»?

Когда мы говорим «merge objects JavaScript», мы подразумеваем создание нового объекта, который содержит все свойства из исходных объектов. Если встречаются одинаковые ключи — значение из второго объекта «перезаписывает» значение из первого.

Допустим, есть два объекта:

const user = {
  name: 'Анна',
  age: 28,
  city: 'Москва'
};

const updates = {
  age: 29,
  job: 'Разработчик'
};

После слияния объектов JS мы хотим получить:

{
  name: 'Анна',
  age: 29,       // обновлённое значение
  city: 'Москва',
  job: 'Разработчик'  // новое свойство
}

Казалось бы, просто. Но дьявол кроется в деталях: вложенные объекты, массивы, мутация оригинала и производительность.

Метод 1: Object.assign() — старый добрый классик

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

Синтаксис

Object.assign(target, ...sources)

Важно: первый аргумент — это целевой объект, который будет изменён. Все последующие — источники свойств.

Пример слияния

const user = { name: 'Анна', age: 28 };
const updates = { age: 29, job: 'Разработчик' };

const merged = Object.assign({}, user, updates);
console.log(merged);
// { name: 'Анна', age: 29, job: 'Разработчик' }

Обратите внимание: мы передаём пустой объект {} как target. Это гарантирует, что исходные объекты не будут мутированы — клонирование объектов JS выполняется корректно.

Подводный камень: поверхностное копирование

Object.assign() выполняет только поверхностное копирование (shallow copy). Если у вас есть вложенные объекты, они будут скопированы по ссылке:

const obj1 = { data: { value: 10 } };
const obj2 = { info: 'test' };

const merged = Object.assign({}, obj1, obj2);
merged.data.value = 999;
console.log(obj1.data.value); // 999 — мутация исходного объекта!

Для глубокого слияния понадобятся другие подходы, о которых мы поговорим ниже.

Метод 2: Spread-оператор — элегантность ES6

С появлением ES6 spread-оператор JavaScript (троеточие ...) стал самым популярным способом объединения свойств объектов. Он лаконичен, читаем и не требует вызова метода.

Синтаксис

const merged = { ...obj1, ...obj2 };

Пример

const defaults = { theme: 'light', lang: 'ru', showSidebar: true };
const userPrefs = { theme: 'dark', fontSize: 16 };

const settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: 'dark', lang: 'ru', showSidebar: true, fontSize: 16 }

Порядок имеет значение: свойства из второго объекта перезаписывают свойства из первого. Именно поэтому theme стал 'dark', а lang остался 'ru'.

Преимущества перед Object.assign()

  • Более короткий и читаемый синтаксис
  • Не нужно помнить про пустой target
  • Легко комбинировать с другими литералами объекта

Однако spread-оператор тоже делает только поверхностное слияние объектов JS.

Метод 3: Глубокое слияние — когда вложенность неизбежна

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

Самописная функция глубокого слияния

function deepMerge(target, source) {
  const result = { ...target };
  
  for (let key in source) {
    if (source.hasOwnProperty(key)) {
      if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
        // Рекурсивно сливаем вложенные объекты
        result[key] = deepMerge(result[key] || {}, source[key]);
      } else {
        // Просто копируем примитивы и массивы
        result[key] = source[key];
      }
    }
  }
  return result;
}

const obj1 = {
  user: { name: 'Иван', address: { city: 'СПб', zip: 190000 } },
  items: [1, 2]
};

const obj2 = {
  user: { age: 30, address: { street: 'Невский' } },
  items: [3, 4]
};

const merged = deepMerge(obj1, obj2);
console.log(merged);
/*
{
  user: {
    name: 'Иван',
    age: 30,
    address: { city: 'СПб', zip: 190000, street: 'Невский' }
  },
  items: [3, 4]  // массивы перезаписываются, а не мержатся
}
*/

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

Готовые библиотеки для глубокого слияния

  • Lodash.merge — самый популярный вариант, рекурсивно сливает любые структуры
  • deepmerge — лёгкая библиотека, только для слияния
  • structuredClone — современный нативный метод (но не сливает, а клонирует)
// Пример с Lodash
import _ from 'lodash';
const merged = _.merge(obj1, obj2);

Метод 4: JSON-трюк — быстрый, но опасный

Иногда разработчики используют JSON.parse(JSON.stringify()) для клонирования и слия

Блоги

Рекомендаций по книгам