Codementor Events

Different methods to copy an object in JavaScript

Published Oct 20, 2018Last updated Oct 22, 2018
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.
Discover and read more posts from Juned Lanja
get started
post comments8Replies
Sahil Singh
5 years ago

Object.assign(a,b) is better than a= Object.assign({},b), as former preserves data type of a. For eg. a could be a float32Array.

Hamed Hemeda
5 years ago

Concise, helpful, direct , thanks

Gaétan Collaud
6 years ago

Hi, I agree with you deep copy. I do the same. But there is some issue with Date.

JSON.stringify will print the date as a string. So when we use JSON.parse the date will now be a string and not a Date object…

Juned Lanja
6 years ago

Yes that’s true. You can only JSON.stringify and JSON.parse object fields that are serializable. It’s won’t work for function typy also. So generaly will help in API that are returning complex data.

But as I said you can write your logic to handle such fileds like function, date, symbols etc or use available libraries.

Show more replies