Different methods to copy an object in JavaScript

Different methods to copy an object in JavaScript
In this post we will discuss the different methods to copy the javascript object and discuss the outcome of each method.
But before that just keep one thing in mind that javascript objects are  mutable  by nature and stored as a reference. So when you assign the object to another variable, you're just assigning the memory address of the object to that variable.
In this case your old and new object both will point to the same memory address. Any change in either object will be reflected in the other. So just assigning the one object to another will not really copies your object!!!
 // Define object bar
var bar= {
    x: 'Hi'
}

console.log(bar.x);
 //Hi
 // Assign it to foo
var foo=bar;
console.log(foo.x);
 //Hi
 //But
foo.x='Hello!! Im foo.';
console.log(foo.x);
 //Hello!! Im foo.
console.log(bar.x);
 //Hello!! Im foo.
bar.x="Nice to meet you foo!!";
console.log(foo.x);
 //Nice to meet you foo!!
console.log(bar.x);
 //Nice to meet you foo!!
As you see in the above example, both  foo  and  bar  are reflecting the change done in either object.
But don't we have 3 short and sweet method that you can use to copy an object.

Shallow copy using  Spread Syntax  or  Object.assign

Spread Syntax
This one is shortest and simple method to copy/merge an object. See below example:
var obj= {
    foo: "foo", bar: "bar"
}

;
var clonedObj= {
    ...obj
}

;
// Object { foo: "foo", bar: "bar" }
Object.assign
The Object.assign() method can be used to copy the values of all enumerable own properties from one or more source objects to a target object, and it will return the target object.
var obj= {
    foo: "foo", bar: "bar"
}

;
var clonedObj=Object.assign( {}

, obj);
// Object { foo: "foo", bar: "bar" }
Using the spread syntax or Object. assign () is a standard way of copying an object in JavaScript. Both methodologies can be equivalently used to copy/merge the enumerable properties of an object to another object.
Problem  with these two approaches is that it will just do the  shallow copy. A shallow copy is a bit-wise copy of an object. A new object is created that has an exact copy of the values in the original object. But if any of the fields of the object are references to other objects, just the reference addresses are copied, i.e., only the memory address is copied. Changing such reference field will be reflected in both objects. See the below example.
let obj= {
    a: 0, b: {
        c: 0
    }
}

;
let copySpread= {
    ...obj
}

;
let copyOA=Object.assign( {}

, obj);
console.log(JSON.stringify(obj));
 // { a: 0, b: { c: 0}}
obj.a=1;
console.log(JSON.stringify(obj));
 // { a: 1, b: { c: 0}}
console.log(JSON.stringify(copySpread));
 // { a: 0, b: { c: 0}}
console.log(JSON.stringify(copyOA));
 // { a: 0, b: { c: 0}}
copySpread.a=2;
console.log(JSON.stringify(obj));
 // { a: 1, b: { c: 0}}
console.log(JSON.stringify(copySpread));
 // { a: 2, b: { c: 0}}
console.log(JSON.stringify(copyOA));
 // { a: 0, b: { c: 0}}
copyOA.a=3;
console.log(JSON.stringify(obj));
 // { a: 1, b: { c: 0}}
console.log(JSON.stringify(copySpread));
 // { a: 2, b: { c: 0}}
console.log(JSON.stringify(copyOA));
 // { a: 3, b: { c: 0}}
obj.b.c=4;
console.log(JSON.stringify(obj));
 // { a: 1, b: { c: 4}}
console.log(JSON.stringify(copySpread));
 // { a: 2, b: { c: 4}}
console.log(JSON.stringify(copyOA));
 // { a: 3, b: { c: 4}}
So these two methods are short and very useful one, but it won't work out when you're having nested object in your object to be copied.

Deep copy using JSON.stringify and JSON.parse

A deep copy occurs when an object is copied along with the objects to which it refers. This can be done easily by using the combination of  JSON.stringify  and  JSON.parse  to create deep copy.
In this method we are first  JSON.stringify()  the json object and again parse it to get json object back. The  JSON.parse()  method parses a JSON string and constructs the JavaScript value or object described by the string. These new object fields will have their own memory address and will be independent of deeply nested object fields  😃
See below example,   deepClone  object won't have any effect if the main source object obj is modified and vice-versa.
  // Deep Clone
obj= {
    a: 0, b: {
        c: 0
    }
}

;
let deepClone=JSON.parse(JSON.stringify(obj));
obj.a=5;
obj.b.c=5;
console.log(JSON.stringify(obj));
 // { a: 5, b: { c: 5}}
console.log(JSON.stringify(deepClone));
 // { a: 0, b: { c: 0}}
deepClone.a=6;
deepClone.b.c=6;
console.log(JSON.stringify(obj));
 // { a: 5, b: { c: 5}}
console.log(JSON.stringify(deepClone));
 // { a: 6, b: { c: 6}}
or you can write your own function to do the deep copy/cloning.

Wrraping up


  1. Remember that Javascript objects are mutable and store by reference.
  2. Object.assign () or Spread syntax can be used for copy but it will be shallow copy.
  3. JSON. stringify and JSON. parse can be used for deep copy.
  4. You can create your own function to do deep copy or use third party libraries like load Lodash, Underscore or many more available there.

Comments

Popular posts from this blog

JS Tip - Required function parameters

JS Tip - Use variable parameters for setTimeout()

Disallow specific imports in Javascript Project