If you are merging two objects that contain other objects or arrays, then you probably want to deeply merge those objects, instead of just shallow merging them. In this lesson, we'll look at three different ways to deeply merge objects, depending on what you want to accomplish: using the spread operator, using lodash's merge
function, or using the deepmerge
npm library.
Instructor: [00:00] We have a person object here that has a name object with a first name of Joe. It says he's 23 years old. It gives Joe's favorite color as green.
[00:11] At some point later, we get an update that we want to apply to the Joe person object, where we want to add the last name of Smith to the name object. We want to overwrite his favorite color with blue instead of green. We want the favorite book entry to be "Harry Potter."
[00:27] If we just went and merged these two together with the spread operator, then what we'd get is a shallow merge. The entire name object from update would just overwrite the name object from the original person, which clears out the first name key and data.
[00:42] The rest of the data we got merged OK though. What we need to do now is a deep merge of the two objects so that this name object is properly merged as well. To do that, we'll extend the spread.
[00:53] Since this is just an object that we're making, we can exactly specify the keys we want and how we want them to be handled. We'll keep the person and update spreads. We'll add a new key for name and spread the name object from the person into that, followed by the name object from the update.
[01:11] The result of that is a new merged object. Inside of that is a new name object with the keys and values from both person and from update. However, this is only two levels deep. It already seems a bit complicated. Let's bring in a library to help us out.
[01:28] In a terminal, I'll yarn add lodash. Back in the file, we can require lodash and then use lodash's merge function, which will handle the deep merge for us. We can say that the merged value is the merge of person and update. Be careful here. If we left it like this, lodash would mutate the person object by merging the update object into it.
[01:52] Instead, just like if we were using Object.assign, we're going to make a brand-new object first and let lodash first merge the person object into that new object and then merge the update object into that object.
[02:05] Now, we have a successfully deeply merged object in one line of code. There's one more case that we're going to worry about though, which is arrays. Let's say our person starts with an array of pets that contains a dog and a lizard.
[02:19] Later, our update contains an array of pets that just says, "Cat." Does that update mean that Joe replaced his dog and lizard with just a cat, or does it mean that he added a cat to his dog and lizard for a total of three pets?
[02:32] With lodash's merge, you don't have a choice. If we run this now, it doesn't actually do either of those things. What it does instead is it treats the arrays like an object, since arrays in JavaScript are actually objects.
[02:45] It first applies the person pets array, which has an element at array index zero and an element at array index one. Then it merges in the pets array from the update, which only has an element at array index zero. It overwrites dog with cat. That's the final answer.
[03:01] That might be what you want to do, but it's not for our case here. We could switch this back to using the deep spread, since the spread operator also works on arrays. With that, we get a pets array that contains all three animals.
[03:16] Again though, we moved away from spread the first time because it was getting complex. It just got bigger now. Let's reach for another library, called deepmerge. We'll yarn add deepmerge and require that.
[03:32] Now, we can deepmerge the person with the update. Deepmerge knows about the array problem. We can pass an option called array merge. That's a function. We can tell deepmerge exactly what we want to do with the arrays.
[03:45] We can give it a function with the destination array and the source array as arguments. We want to return a new array. We'll use spread here to say that we want to concatenate the two arrays together.
[03:56] Now when we run that, it works. We get a deeply merged object with the pet array handled like we want. When merging objects, the spread operator works great. It's fully customizable, but it can get tedious if the objects are very deeply nested or of an unknown structure.
[04:12] Lodash's merge works, but only if we want to treat arrays like objects. Deepmerge works. We can provide a custom array-handling function.