Clone or copy javascript object in 4 different ways

Cloning an object means creating its exact copy. Cloned object would have the same properties and methods as the source object. There are different ways of creating a clone of an object in javascript.

Method 1: Iterating over source object
Iterate over the object which needs to be cloned using forin loop and assign the key value in each iteration to the target object. Example,

// source object
let car = {
           color: 'red',
           brand: 'BMW',
           print: function() {
                    console.log('Car object');
           }
};
// declare the target object
const clone = {};
// iterate over properties of source object
for(let key in car) {
   // create a new property in target object
   clone[key] = car[key];
}
document.write(JSON.stringify(clone));

Source object has two properties and a function.
Note that the syntax clone[key] = car[key] assigns the value of the key from the right side object to the corresponding property of the left side object.
A new property in the left object is added if it does not exist.
Thus, in the first iteration, this syntax is evaluated to clone[color] = car[color]
When the cloned object is printed to the browser window, following is the output.

{color: “red“, brand: “BMW“, print: ƒ}

As you can see, the cloned object has same properties and function.

Method 2: Using Object class
Above method is the older and longer way of cloning an object. Modern javascript provides a more concise way of cloning an object using assign method of Object class.
This method copies the properties from one or more source objects to a target object and returns the new object.
It takes at least 2 arguments, the first one being the target object and the second is source object. There may be more than 1 source objects also, in which case, they will be supplied as arguments 2, 3, 4…so on. Example,

// source object
let car = {
           color: 'red',
           brand: 'BMW',
           print: function() {
                    console.log('Car object');
           }
};
// copy car object into a new object
const clone = Object.assign({}, car);
document.write(JSON.stringify(clone));

Note that we are passing an empty object as the target object to the assign method but we may also pass an existing object. In this case, the properties and functions of the source object(s) are added to the pre-existing properties of the target object.
If the target object has some property names that match with the source object, then their values are overwritten with source values.

This method can only perform shallow cloning. This means that if any property of a source object is another object, then it will copy the reference to that object in the target object and both the references will point to the same object.
If the source object only contains simple values, then this is the most recommended method.

This method can also be used to copy(or clone) an array. The first argument to assign method should be empty square brackets([]) which is the symbol for an array and you will get a cloned array. Example,

let arr = [1, 3, 45];
const clone = Object.assign([],arr);
document.write(JSON.stringify(clone));

Method 3: Using spread operator
Spread operator allows the object to be expanded. Its syntax is a simple three dots(...) followed by the name of object and can be used to copy and object. Example,

// source object
let car = {
           color: 'red',
           brand: 'BMW',
           print: function() {
                    console.log('Car object');
           }
};
// copy using spread operator
const clone = {...car};

Spread operator was added in ES6.
This method can be used to copy(or clone) an array. The only difference is that the spread operator will be surrounded by square brackets instead of curly braces since square brackets are the symbol of an array. Example,

let arr = [1, 3, 45];
const clone = [...arr];
document.write(JSON.stringify(clone));

This method creates a shallow copy of an object meaning that if an object contains nested object, then it creates copy of nested objects.
This means that changes done to those nested objects will also be reflected in the original object.

Method 4: Converting to JSON
JSON stands for JavaScript Object Notation. A JSON object is similar to a javascript object that we have been dealing in this section. It has properties in key-value format and functions.
Javascript’s JSON class has methods that can be used to clone an object. Example,

// source object
let car = {
           color: 'red',
           brand: 'BMW',
           print: function() {
                    console.log('Car object');
           }
};
const clone = JSON.parse(JSON.stringify(car)));

JSON.stringify takes an object as argument and converts it into its string representation while JSON.parse takes a string as argument and returns its object representation. Both these methods are clubbed together to create a copy of an object.
This method creates a deep copy of an object meaning that if an object contains nested object, then it creates clone of nested objects too.
This means that changes done to those nested objects will not affect the original object.
Use this method only when the source object is convertible(can be parsed) to a JSON object else it will throw an error.

JSON.stringify method can be used to convert an object to a string. This string will be in JSON notation and is used to transfer data between client(browser) and server.

This method can also be used to clone an array. Just supply an array in place of an object to JSON.stringify method and the returned object will be the copy of the source array. Example,

let arr = [1, 3, 45];
const clone = JSON.parse(JSON.stringify(arr)));
document.write(clone);

Deep copy and shallow copy
A javascript object may also contain another object inside it(also called nested object). When an object is cloned such that if the nested object of clone is changed, then the corresponding original object is also modified, it is called shallow copy.
If the object is cloned in such a way that modifying the nested object does not affect the original object, then it is called deep cloning.
Thus, shallow and deep cloning only differ if the original object contains a nested object.
Out of all the methods described above, only JSON.parse(Method 4) performs deep copy, rest all perform shallow cloning.
Shallow cloning example
Consider the object given below.

 const student = { name : "Ab cd", age : 12, details : { section : "Science" } };

It contains a nested object. Now perform a copy using spread operator and modify a property of nested object.

  const student = {
               name : "Ab cd",
               age : 12,
               details : {
                          section : "Science"
                         }
               };
  // create clone
  const clone = {...student};
  document.write("Original object before modifying: " + JSON.stringify(student));
  document.write("<br>");
  document.write("Clone before modifying: " + JSON.stringify(clone));
  document.write("<br>-----------------<br>");
        // modify nested object
  clone.details.section = "Arts";
  document.write("Original object after modifying: " + JSON.stringify(student));
  document.write("<br>");
  document.write("Clone after modifying: " + JSON.stringify(clone));

Above code prints

Original object before modifying: {“name”:”Ab cd”,”age”:12,”details”:{“section”:”Science”}}
Clone before modifying: {“name”:”Ab cd”,”age”:12,”details”:{“section”:”Science”}}
—————–
Original object after modifying: {“name”:”Ab cd”,”age”:12,”details”: {“section”:”Arts”} }
Clone after modifying: {“name”:”Ab cd”,”age”:12,”details”:{“section”:”Arts”}}

Look, modifying nested object in clone also affects the corresponding original object.
Deep cloning example
Now let’s modify the above example  to perform cloning using JSON.parse(Method 4). Modified example would become

const student = {
             name : "Ab cd",
             age : 12,
             details : {
                        section : "Science"
                       }
             };
// create clone
const clone = JSON.parse(JSON.stringify(student));
document.write("Original object before modifying: " + JSON.stringify(student));
document.write("<br>");
document.write("Clone before modifying: " + JSON.stringify(clone));
document.write("<br>-----------------<br>");
// modify nested object
clone.details.section = "Arts";
document.write("Original object after modifying: " + JSON.stringify(student));
document.write("<br>");
document.write("Clone after modifying: " + JSON.stringify(clone));

Above code prints

Original object before modifying: {“name”:”Ab cd”,”age”:12,”details”:{“section”:”Science”}}
Clone before modifying: {“name”:”Ab cd”,”age”:12,”details”:{“section”:”Science”}}
—————–
Original object after modifying: {“name”:”Ab cd”,”age”:12,”details”: {“section”:”Science”} }
Clone after modifying: {“name”:”Ab cd”,”age”:12,”details”:{“section”:”Arts”}}

Look, modifying nested object of clone does not affect the corresponding original object. This method creates deep clone.
Hit the clap icon if the article was useful.

Leave a Reply