Shallow Copying / Cloning Objects in JavaScript

Many times we need to copy/clone objects. JavaScript offers multiple solutions to this problem. In this article, we’ll compare some of them.

Object.assign Method

Let’s create a person object and clone it with Object.assign in below example:

const person = {
name: 'john',
age: 35,
interests: { javascript: true }
};
const clone = Object.assign({}, person);console.log(clone);
// { name: 'john', age: 35, interests: { javascript: true } }

Printing values from the clone object show the clone has the same properties and values as the person object.

What Object.assign does is, it copies the properties and their values from the second argument (and latter arguments if they exist) into the first argument (the target object) and returns the first argument. Because we passed an empty object literal as the target argument, the returned value is the shallow copy of the person object.

The word shallow is the key here. Let’s append below code into our example and see what happens if we change values on the source person object:

...person.name = 'jane';
person.age = 40;
person.interests.javascript = false;
console.log(person);
// { name: 'jane', age: 40, interests: { javascript: false } }
console.log(clone);
// { name: 'john', age: 35, interests: { javascript: false } }

Changed name and age values on person object did not have any effect on the clone object. However, interest is changed on both objects. Is this expected?

The short answer is yes! Shallow cloning copies values of all properties with primitive types. However, Object and Array properties are references and referenced Objects / Arrays will not be copied into a shallow clone. Instead, the references are copied. interest is a nested object inside person object and only its reference is copied into the clone. Both objects have reference to the same interest object, therefore changing interest property using person object will directly change the clone object’s interest and vice versa.

To overcome this issue, deep cloning must be performed instead of shallow cloning. Deep cloning will not be covered in this article but it is a good candidate for the next one.

Object.assign is a powerful function and has many other uses but, let’s focus on shallow cloning and see alternative methods.

Spread Operator ( ... syntax) Method

The spread operator comes with ECMAScript 2018 standard and is now supported by most modern browsers and NodeJS by default. Its usage is pretty and simple. Just replace the cloning line in the above example with the following:

const clone = { ...person };

And that’s it! The spread operator is readable and elegant. What it does is spreading the properties of person object into an empty object literal.

Spread operator also very powerful and has multiple uses like copying, extending, concatenating objects and arrays, spreading arrays into function arguments, array/object destructuring and more. We’ll dive into spread operator in another article.

Lodash Method

Most of the time it is a good idea to use a utility library in our applications. Although JavaScript has gotten more and more powerful over the years, its standard toolset does not cover all of our ambitious requirements. At this point, utility libraries join the action. Lodash is a popular choice. Here’s how it’s done in _ :

const _ = require('lodash');...const clone = _.clone(person);

Again, readable and elegant. Lodash also supports deep cloning out of the box with its cloneDeep method.

Conclusion

We demonstrated 3 ways of shallow cloning:

Object.assign({}, person); // Old-school JS
const clone = { ...person }; // Spread operator
const clone = _.clone(person); // Lodash method

Which one is your preferred method? Do you use other alternatives? Please write in the comments. Don’t forget to support with your claps and shares if you like the article. Happy coding!