Как объединить свойства двух объектов JavaScript? (Object.assign, spread и другие способы)
Лучший способ: оператор spread (расширение) — современный и нативный
Вы уже на верном пути. Оператор ... (spread) — это самый простой и читаемый способ объединить свойства двух объектов в современном JavaScript (ES2018+). Ваш код корректен:
const merged = { ...defaultSettings, ...userSettings };
Принцип работы: свойства из второго объекта (userSettings) перезаписывают одноимённые свойства из первого (defaultSettings). Свойства, которые есть только в одном объекте, просто копируются. Это называется "поверхностное (shallow) объединение".
Альтернативный нативный метод: Object.assign()
До появления spread-оператора использовали Object.assign():
const merged = Object.assign({}, defaultSettings, userSettings);
Первый аргумент — пустой целевой объект (чтобы не мутировать исходные). Последующие объекты добавляются слева направо. Результат идентичен spread-оператору, но код чуть многословнее.
Важное предостережение: вложенные объекты (глубокое объединение)
И spread, и Object.assign() делают только поверхностное копирование. Если у вас есть вложенные объекты, они будут перезаписаны целиком, а не объединены рекурсивно. Пример:
const obj1 = {
user: { name: 'Alice', age: 25 },
role: 'admin'
};
const obj2 = {
user: { name: 'Bob' } // age пропадёт!
};
const merged = { ...obj1, ...obj2 };
console.log(merged);
// { user: { name: 'Bob' }, role: 'admin' }
// age: 25 потеряно!
Для глубокого (deep) объединения вложенных объектов нативный JavaScript не предоставляет встроенного метода. Вот три решения:
- Рекурсивная функция (напишите сами):
function deepMerge(target, source) {
const output = { ...target };
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
output[key] = deepMerge(target[key] || {}, source[key]);
} else {
output[key] = source[key];
}
}
}
return output;
}
const deepMerged = deepMerge(obj1, obj2);
// { user: { name: 'Bob', age: 25 }, role: 'admin' }
- Используйте библиотеку Lodash (метод
_.merge()):
// Подключите lodash: npm install lodash
const _ = require('lodash');
const merged = _.merge({}, obj1, obj2);
// Работает рекурсивно, не мутирует исходные объекты
- Структурированное клонирование (только для глубокого копирования, не объединения):
const copy = structuredClone(originalObject);
// Но это не объединяет, а копирует один объект
Рекомендации по выбору
- Для плоских объектов (без вложенности) — используйте spread-оператор. Это современно, быстро и читаемо.
- Для глубокого объединения — либо напишите свою рекурсивную функцию (если логика простая), либо используйте
_.merge()из Lodash (если проект уже использует эту библиотеку). - Избегайте мутации исходных объектов — всегда создавайте новый объект (пустой
{}как первый аргумент вObject.assignили пустой объект слева от spread).
Ваш пример с настройками — идеальный случай для spread-оператора. Он решает задачу в одну строку и не требует дополнительных зависимостей.
<<Альтернативный подход: использование JSON для глубокого копирования (с осторожностью)
Если вам нужно быстрое глубокое объединение без внешних библиотек, можно использовать трюк с JSON. Однако этот метод не рекомендуется для production из-за ограничений:
function deepMergeJSON(target, source) {
// Превращаем всё в строку и обратно, но теряем функции, undefined, Symbol, даты
const merged = JSON.parse(JSON.stringify(target));
const sourceCopy = JSON.parse(JSON.stringify(source));
for (let key in sourceCopy) {
if (typeof sourceCopy[key] === 'object' && !Array.isArray(sourceCopy[key])) {
merged[key] = { ...merged[key], ...sourceCopy[key] };
} else {
merged[key] = sourceCopy[key];
}
}
return merged;
}
const result = deepMergeJSON(obj1, obj2);
// Работает, но не рекурсивно для глубокой вложенности!
Недостатки:
- Теряются значения
undefined, функции,Symbol,Date(превращаются в строки). - Не работает с циклическими ссылками.
- Медленнее нативных методов.
- Не делает полное глубокое объединение — только один уровень вложенности.
Когда это может пригодиться: только для простых объектов, содержащих примитивы и вложенные объекты без специальных типов данных. В остальных случаях лучше использовать рекурсивную функцию или Lodash.
Также стоит упомянуть, что в будущем в JavaScript может появиться нативный метод Object.merge() (предложение находится на стадии рассмотрения), но пока это не стандарт.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги