Merging two object into one was always a challenge for me. While the use cases for it can be quite common like assigning default properties to a configuration object.
I never really had a go to solution for solving that problem until I found out about Defu by UnJS organization. I discovered this tool while working on one of my Nuxt modules and it has proven to be extremely useful in many different cases.
But apart from the fact that it delivers a great value out of the box, you can also customise it for more advanced cases where you may not want a default merging strategy in some cases. I will show you an example later on that I am using on a daily basis in my Nuxt Security module.
Enjoy!
What is Defu?
Defu is a JavaScript package that allows you to assign default properties, recursively and it is really lightweight and fast.
So, basically what it does it allows you to efficiently merge two objects into one.
Usage
In order to use Defu in your application, first install the package like following:
yarn add defu
And that's it! You can start using defu in your app like following:
import { defu } from "defu";
const options = defu(object, ...defaults);
The options
object will have a structure of combined object
and ...defaults
.
To give you more insights into how it will work, let's take a look at this real example:
import { defu } from "defu";
const defaults = { a: { b: 1, c: 3 } }
const options = { a: { b: 2 } }
const mergedOptions = defu(options, defaults)
console.log(mergedOptions);
// => { a: { b: 2, c: 3 } }
As you can see from the example above, the value of mergedOptions
is { a: { b: 2, c: 3 } }
which means that Defu took the structure of defaults
object and assigned properties from options
object into it instead of replacing the existing a
object property as it would be done normally.
Quite useful if you ask me ;)
More advanced use cases
Sometimes default merging strategy is not enough. Using createDefu
it is possible to create a custom instance with different merging strategy.
createDefu
function accepts obj (source object), key and value (current value) and should return true if applied custom merging.
Let's take a look at following example where we want to sum numbers instead of overriding the properties:
import { createDefu } from "defu";
const sumDefu = createDefu((obj, key, value) => {
if (typeof obj[key] === "number" && typeof value === "number") {
obj[key] += value;
return true;
}
});
sumDefu({ cost: 5 }, { cost: 10 }); // { cost: 15 }
You can see already how useful this package can be. And this is just the beginning! Take a look at the README.md for more examples https://github.com/unjs/defu
Bonus - usage of Defu in Nuxt Security
If you are have not yet seen NuxtSecurity I highly recommend you to try it out! It is a module that helps you make more secure Nuxt apps by default. It comes with useful features like Security response headers and middleware like Rate Limiter, CORS, CQRS, XSS, and many more!
In NuxtSecurity, I was using the default merging strategy of Defu but at certain point I realised that it does not work the way I wanted if there was an array passed as an object property (common case for Browser response headers where values as arrays).
So one of the community contributors Qrzy (Marcin Kurkiewicz) created a custom defu merger that would help with this array issue:
import { createDefu } from 'defu'
export const defuReplaceArray = createDefu((obj, key, value) => {
if (Array.isArray(obj[key]) || Array.isArray(value)) {
obj[key] = value
return true
}
})
And it is working really well until today!
Courses & Certifications
If you are looking for great courses and certifications to practice Vue, Nuxt, JavaScript, and more, check out following links:
Summary
Nicely done! You have just learned how to use Defu to efficiently merge objects. Let me know what other advanced use cases you have in your apps :)
Take care and see you next time!
Top comments (4)
Thanks for the article. Generally, what is the advantage of defu over plain
Object.assign
or just spread syntax?Heyo!
Generally, with Object.assign, the result of the following operation will be:
While with defu it will be:
So generally if a property is an object, defu will try to combine both properties and maintain the structure of the object instead of overriding it like normal object.assign does that.
Incredible, thank you. I will try to use NuxtSecurity and defu in my next project :)
Awesome! If you will find any things that could be done better, do not hesitate to let us know :)