Be aware when cloning objects in JavaScript! 👯‍♀️

Chris Bongers - Nov 3 '20 - - Dev Community

Now and then you'll need to clone an object in JavaScript, mainly one to be modified but you still want the original to stay the same.

Let's say for this purpose we have a duplicate and change function.

Meaning we have an object, which we will duplicate and then change.
The original, of course, will need to stay the same.

Benchmark JavaScript clone

In JavaScript we can ofcourse clone a object by assigning it to a new const like this:

const original = { color: '🔴', child: { action: 'stop' } };
const clone = original;

console.log(original); // {color: "🔴", child: {action: "stop"}}
console.log(clone); // {color: "🔴", child: {action: "stop"}}
Enter fullscreen mode Exit fullscreen mode

Ok wow that works, cool done!

But not really, here comes the issue with this.

clone.color = '🟢';
console.log(original); // {color: "🟢", child: {action: "stop"}}
console.log(clone); // {color: "🟢", child: {action: "stop"}}
Enter fullscreen mode Exit fullscreen mode

Hmm that's not cool, now our original one is also modified!

This is caused because of objects being reference types. When we choose to use = to clone, we make a pointer to object one instead of actually cloning it.

Clone using the spread operator

The spread operator is introduced in ES6 so fairly new, and not in the official specs yet!

To use it, you create a new object prefixed by three dots ...

const original = { color: '🔴', child: { action: 'stop' } };
const spread = {...original};
console.log(original); // { color: '🔴', child: { action: 'stop' } }
console.log(spread); // { color: '🔴', child: { action: 'stop' } }
Enter fullscreen mode Exit fullscreen mode

Ok, our basic clone works again, now let's check the change

spread.color = '🟢';
console.log(original); // { color: '🔴', child: { action: 'stop' } }
console.log(spread); // { color: '🟢', child: { action: 'stop' } }
Enter fullscreen mode Exit fullscreen mode

Yes, we did it!

But wait let's make sure we can also modify the child element.

spread.color = '🟢';
spread.child.action = 'start';
console.log(original); // { color: '🔴', child: { action: 'start' } }
console.log(spread); // { color: '🟢', child: { action: 'start' } }
Enter fullscreen mode Exit fullscreen mode

Wait, what just happened?

This is because the spread operator is a shallow copy, so only the first level will be actually copied, the rest will be assigned.

Clone in JavaScript using Object.assign

This is by far the method you will read the most about. It's basically the old version of the spread operator.

You can use it as follows:

const original = { color: '🔴', child: { action: 'stop' } };
const assign = Object.assign({}, original);
console.log(original); // { color: '🔴', child: { action: 'stop' } }
console.log(assign); // { color: '🔴', child: { action: 'stop' } }
Enter fullscreen mode Exit fullscreen mode

Cool, this also clones, but let's check if it modifies correctly.

assign.color = '🟢';
assign.child.action = 'start';
console.log(original); // { color: '🔴', child: { action: 'start' } }
console.log(assign); // { color: '🟢', child: { action: 'start' } }
Enter fullscreen mode Exit fullscreen mode

Damn, still the same issue turns out Object.assign is also a shallow copy.

So now what?

Using JSON to clone

A quick and dirty hack to deep-clone is using JSON to stringify and then parse the object again.

This is not a "best-practice" but used by many people, and good enough for basic cloning.

For more robust deep-clone make use of packages like lodash cloneDeep.

It works like this:

const original = { color: '🔴', child: { action: 'stop' } };
const json = JSON.parse(JSON.stringify(original));
console.log(original); // { color: '🔴', child: { action: 'stop' } }
console.log(json); // { color: '🔴', child: { action: 'stop' } }
Enter fullscreen mode Exit fullscreen mode

Awesome, does the exact same thing, but let's see when we modify data.

json.color = '🟢';
json.child.action = 'start';
console.log(original); // { color: '🔴', child: { action: 'stop' } }
console.log(json); // { color: '🟢', child: { action: 'start' } }
Enter fullscreen mode Exit fullscreen mode

Yes, we did it! A fully cloned object that we can modify!

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player