Lodash is a very useful utility library that lets us work with objects and arrays easily.
However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.
In this article, we’ll look at how to implement some Lodash object merging methods ourselves with the spread operator and plain JavaScript object operators and methods.
assign
The Lodash’s assign
method assigns all of an object’s own enumerable string keyed properties of the source object to the destination object.
Source objects are applied from left to right. Plain JavaScript already has the Object.assign
method in its standard library, so we can use that to implement this method.
The assign
method mutates the original object to add the keys of the other objects to it.
For instance, we can do that as follows:
const assign = (obj, ...sources) => {
for (const s of sources) {
obj = {
...obj,
...s
};
}
return obj;
}
In the code above, we have our own assign
function, which takes the same arguments as Lodash’s assign
method. It takes obj
, which is the original object. The sources
are the objects that we want to merge into obj
.
Then we have a for...of
loop, which loops through the sources
, which is an array of object originating from the arguments that we passed in because we applied the rest operator to it.
In the loop, we applied the spread operator to obj
and each object in sources
to merge them into one. Then we return obj
.
We can also use the plain JavaScript’s Object.assign
method to do the same thing as follows:
const assign = (obj, ...sources) => {
return Object.assign(obj, ...sources);
}
We just called Object.assign
with obj
as the first argument, and the sources
array spread as the arguments of the assign
method’s subsequent arguments.
In the end, we can call either one as follows:
function Foo() {
this.a = 1;
}
function Bar() {
this.c = 3;
}
Foo.prototype.b = 2;
Bar.prototype.d = 4;
console.log(assign({
'a': 0
}, new Foo(), new Bar()));
Then we get that the console log outputs {a: 1, c: 3}
since it merges in the source objects’ own enumerable properties only, which don’t include any properties in the prototype.
assignIn
The Lodash assignIn
method is like the assign
method, but it also merges the source object’s prototypes’ properties into the object.
Therefore, we can implement it in a similar way as the assign
function, except that we need to call the Object.getPrototypeOf
method to get the prototype of the objects that we have in sources
so that we can merge their prototypes’ properties into our returned object.
For instance, we can implement assignIn
in the following way:
const assignIn = (obj, ...sources) => {
for (const s of sources) {
let source = s;
let prototype = Object.getPrototypeOf(s)
while (prototype) {
source = {
...source,
...prototype
}
prototype = Object.getPrototypeOf(prototype)
}
obj = {
...obj,
...source
};
}
return obj;
}
In the code above, we have the same parameters and the same for...of
loop as assignIn
.
However, inside the loop, we have the source
and prototype
variables. The prototype
variable is used to traverse up the object’s prototype chain to merge all its prototypes’ properties into it up the prototype chain. We did the traversal with the Object.getPrototypeOf
method and the while
loop.
Then we used the spread operator to merge in the source
object with all its prototypes’ properties merged in into the obj
object.
Now, when we call assignIn
as follows:
function Foo() {
this.a = 1;
}
function Bar() {
this.c = 3;
}
Foo.prototype.b = 2;
Bar.prototype.d = 4;
console.log(assignIn({
'a': 0
}, new Foo(), new Bar()));
We get {a: 1, b: 2, c: 3, d: 4}
as the value logged from the console log because all of Foo
and Bar
instance variables have been added to the Foo
and Bar
instances as their own properties.
Conclusion
To implement the Lodash assign
method, we just need to use the spread operator to merge the object’s own properties into the object that we want to have the properties merged in.
The assignIn
method is more complex because we have to traverse up the prototype chain to merge in all those properties as well. We can do that by using a while
loop with the Object.getPrototypeOf
method.