Слияние (merge) — операция над объектами, выполняющая их объединение. Она появляется там, где необходимо данные одного объекта перенести в другой объект.
Слияние часто используется при работе с веб-формами. Например, когда пользователь меняет свои персональные данные в настройках аккаунта, измененные данные приходят в приложение в виде объекта. Данные из этого объекта нужно перенести в объект пользователя. Так происходит обновление пользователя:
// Такой пользователь есть в системе
const user = { name: 'Tirion', email: 'support@hexlet.io', age: 44 }
// Из формы пришли данные
const data = { name: 'Tirion 2', age: 33 }
// В результате должно получиться
// { name: 'Tirion 2', email: 'support@hexlet.io', age: 33 };
Решение в лоб — перенести каждое свойство отдельно:
user.name = data.name
user.age = data.age
// Где-то тут сохраняем пользователя в базе данных
Прямой перенос хорошо работает, когда данных мало и их структура не меняется. Если же данных много или в разные моменты времени могут приходить разные данные, то это превращается в кучу одинакового кода:
if (Object.hasOwn(data, 'name')) {
user.name = data.name
}
// И так нужно перечислить все возможные свойства
С помощью слияния (часто говорят «мержа») мы можем сократить все до одной строчки:
Object.assign(user, data)
console.log(user)
// => { name: 'Tirion 2', email: 'support@hexlet.io', age: 33 };
Метод Object.assign() берёт объект, переданный первым параметром, и переносит в него всё из объектов, переданных остальными параметрами. В нашей ситуации это один объект, переданный вторым параметром.
Слияние работает так. Если какое-то свойство было только в первом объекте, то оно остается тем, что и было. Если свойство присутствует во втором (и далее) объекте, то оно записывается в первый независимо от того, было оно там или нет. Поэтому, если свойство присутствовало и в первом объекте и во втором, то оно будет перезаписано значением из второго объекта:
const obj1 = { a: 'a', b: 'b' }
const obj2 = { c: 'c', b: 'v' }
Object.assign(obj1, obj2)
console.log(obj1)
// => { a: 'a', b: 'v', c: 'c' }
У метода Object.assign()
есть одно ограничение: он выполняет только поверхностное слияние. Вложенные объекты не сравниваются, а просто заменяются:
const obj1 = { a: { a: 1 } }
const obj2 = { a: { b: 1 } }
Object.assign(obj1, obj2)
console.log(obj1)
// => { a: { b: 1 } }
// пример глубокого (рекурсивного) слияния
// используется метод merge() библиотеки lodash
import _ from 'lodash'
_.merge(obj1, obj2)
// => { a: { a: 1, b: 1 } }
Как и любой другой мощный механизм, слияние нуждается в аккуратном использовании. В объектах бывают поля, которые не должны быть перезаписаны при слиянии, например, количество денег на счету у пользователя. Если не контролировать состав данных из второго объекта, то туда могут попасть свойства (случайно или злонамеренно), которые приведут к перезаписыванию важных свойств.
Если говорить про веб-формы, то технически всегда можно послать больше данных, чем описано в форме.
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.