Как объединить глубоко вложенные объекты в JavaScript
При работе в JavaScript иногда возникает потребность объединить два объекта, которые могут быть глубоко вложенными.
В этой статье мы увидим, как с этим справиться правильно.
Давайте начнем
Допустим, у нас есть такой пользовательский объект:
const user = {
name: "David",
phone: 122345678,
location: {
city: "Camden",
country: "UK"
}
};
И мы хотим обновить этот объект новыми значениями. Например, при обновлении своего профиля пользователя пользователь вводит новые значения, поэтому нам нужно объединить предыдущий объект с новым обновленным объектом.
Если пользователь обновит только некоторые значения, у нас будет такой объект:
const updates = {
name: "David",
phone: 123456789,
location: {
city: "Smithfield"
}
};
Как вы можете видеть, объект пользователя имеет свойство location
с свойствами city
и country
внутри него. Но в объекте обновлений у нас нет свойства страны, так как мы можем объединить эти объекты?
Попробуем известными способами.
Использование Object.assign
const user = {
name: 'David',
phone: 122345678,
location: {
city: 'Camden',
country: 'UK'
}
};
const updates = {
name: 'David',
phone: 123456789,
location: {
city: 'Smithfield'
}
};
console.log(Object.assign({}, user, updates));
/* output:
{
name: 'David',
phone: 123456789,
location: {
city: 'Smithfield'
}
}
*/
Как видите, свойство location
из объекта обновления полностью заменило предыдущий объект location
, поэтому свойство country
потеряно.
Это потому, что Object.assign выполняет неглубокое слияние. Неглубокое слияние означает, что оно объединит свойства только на первом уровне, а не на вложенном уровне.
Использование оператора распростронения
const user = {
name: 'David',
phone: 122345678,
location: {
city: 'Camden',
country: 'UK'
}
};
const updates = {
name: 'David',
phone: 123456789,
location: {
city: 'Smithfield'
}
};
console.log({ ...user, ...updates });
/* output:
{
name: 'David',
phone: 123456789,
location: {
city: 'Smithfield'
}
}
*/
Как видите, это также дает тот же результат, потому что Object.assign и оператор распространения просто неглубоко объединяют объекты.
Итак, чтобы исправить это и правильно объединить два глубоко вложенных объекта, мы можем использовать метод merge
, предоставляемый очень популярной библиотекой lodash.
Использование Lodash merge
const user = {
name: "David",
phone: 122345678,
location: {
city: "Camden",
country: "UK"
}
};
const updates = {
name: "David",
phone: 123456789,
location: {
city: "Smithfield"
}
};
console.log(_.merge(user, updates));
/* output:
{
name: 'David',
phone: 123456789,
location: {
country: 'UK',
city: 'Smithfield'
}
}
*/
Теперь все работает, как ожидалось, и country не теряется при слиянии.
Lodash - лучшая библиотека, которая имеет множество функций для реальных приложений.