Cloning and Merging in JavaScript

Cloning and merging, Object.assign

Copying an object variable creates one more reference to the same object. What if we need to duplicate an object?

We can use the method Object.assign for that:

1
Object.assign(dest[,src1,src2,...])

It copies the properties of all object src1, src2, ... into dest. In other words, properties of all arguments starting from the 2nd are copied into the 1st, then it returns dest

1
2
3
4
5
6
7
let user = { name: "John"};

let permission1 = { canView: true};
let permission2 = { canEdit: true};

Object.assign(user, permission1, permisson2);
// now user = {name:"John", canView: true, canEdit: true}

If the receiving object (user) already has the same named property, it will overwritten:

1
2
3
4
5
6
let user = { name: "John" };

// overwrite name, add isAdmin
Object.assign(user, { name: "Pete", isAdmin: true });

// now user = { name: "Pete", isAdmin: true }

Until now we assumed that all properties of user are primitive, But properties can be references to other object. What do do with them? Like this:

1
2
3
4
5
6
7
8
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}};

alert( user.sizes.height ); // 182

Now it’s not enough to copy clone.sizes = user.sizes, because the user.sizes is an object, it will be copied by reference. So clone and user will share the same sizes. Like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};

let clone = Object.assign({}, user);

alert( user.sizes === clone.sizes ); // true, same object

// user and clone share sizes
user.sizes.width++; // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one

To fix that, we use “deep cloning” that examine each value of user[key], if it’s an object, replicate its structure as well.
There’s a standard algorithm for deep cloning that handles the case above and more complex cases, called the Structured cloning algorithm. We can use an implementation of a JavaScript library lodash, the method is called _.cloneDeep(obj)