DEV Community

Ravi kumar
Ravi kumar

Posted on

How to Copy object?

Hey guys, so this topic is about how to copy an object without changing the original one because sometimes we copied an object without knowing that accidentally we changed the original object too.

So Let's start


Understanding Deep and Shallow Copy

In a reassignment operation involving primitive data types such as strings, numbers, and booleans, the original variable is copied by JavaScript.

For example,

y = x //  x is copied into y

y++ // y is incremented

console.log(y) // now 4
console.log(x) // still 3
Enter fullscreen mode Exit fullscreen mode

In this case, the value 3 is copied into y, and then x is disconnected from y. So mutating y does not affect x.

Conversely, with non-primitive data types like arrays and objects, only a reference to the values is passed. So when the copy is mutated, the original also gets mutated. This is also known as shallow copying.

let aalu = {name: "aalu"};

let bhalu = aalu;
bhalu.name = "bhalu";

console.log(aalu.name);  // outputs "bhalu"
console.log(bhalu.name); // outputs "bhalu"
Enter fullscreen mode Exit fullscreen mode

If we instead want to copy an object so that we can modify it without affecting the original object, we need to make a deep copy.


So let's talk about copying Obj

1. JSON.stringify() and JSON.parse()

So first talk about what is JSON.stringify() and JSON.parse()?

JSON.stringify() : This method converts a JavaScript object or value to a JSON string.

JSON.parse(): This method parses a JSON string, constructing the JavaScript value or object described by the string.

We can combine both of these methods to create a copy of an object like this:

const user = {
    name: "JSON",
    age: "21",
    job: "standard file format and data interchange format",
}

let clone = JSON.parse(JSON.stringify(user))

console.log(user)
console.log(clone)

/*
{
  age: 21,
  job: "standard file format and data interchange format",
  name: "JSON"
}
{
  age: 21,
  job: "standard file format and data interchange format",
  name: "JSON"
}
*/
Enter fullscreen mode Exit fullscreen mode

When the copy object is mutated, the original object stays the same:

clone.age = 32

console.log(user)
console.log(clone)

/*
{
  age: 21,
  job: "standard file format and data interchange format",
  name: "JSON"
}
{
  age: 32,
  job: "standard file format and data interchange format",
  name: "JSON"
}
Enter fullscreen mode Exit fullscreen mode

However, this will also create a problem when we are working with a function that was inside a function.

Suppose we have a method in our object user called incrementAge:

const user = {
    name: "JSON",
    age: "21",
    job: "standard file format and data interchange format",
    incrementAge: function() {
         this.age++
    }
}
Enter fullscreen mode Exit fullscreen mode

The function will not be available in the copied object. Thus, this method achieves deep copy only if there is no function within the object.

Object.assign()

Among the object constructor methods, Object.assign() is used to copy the values and properties from one or more source objects to a target object. It returns the target object, which has properties and values copied from the source object.

const user = {
    name: "JSON",
    age: "21",
    job: "standard file format and data interchange format",
    incrementAge: function() {
         this.age++
    }
}

let clone = Object.assign({}, user) // Copies user into clone

clone.age = 32

console.log(user)
console.log(clone)

/*
{
     age: 21,
     incrementAge: function() {
       this.age++
     },
     job: "standard file format and data interchange format",
     name: "JSON"
}
{
     age: 32,
     incrementAge: function() {
       this.age++
     },
     job: "standard file format and data interchange format",
     name: "JSON"
}
*/
Enter fullscreen mode Exit fullscreen mode

However, one thing to remember about Object.assign() is that the method only performs a partial deep copy on objects.

To understand what that means, let's consider the following:

const user = {
    name: "JSON",
    age: 21,
    job: "standard file format and data interchange format",
    location: {
      city: "Lagos",
    }
}

const clone = Object.assign({}, user)

clone.age = 32
clone.location.city = "New York"

console.log(user)
console.log(clone)

/*
{
  age: 21,
  job: "standard file format and data interchange format",
  location: {
       city: "New York",
  },
  name: "JSON",
}

{
  age: 32,
  job: "standard file format and data interchange format",
  location: {
       city: "New York",
  },
  name: "JSON",
}
*/
Enter fullscreen mode Exit fullscreen mode

Whenever we mutate a property within the nested object (in clone), it will also mutate the same property in the original object (user). While the age property in the original object remained untouched, the city property was mutated by the reassignment operation. Hence, the Object.assign() method should be used to deep copy objects that have no nested objects.

The Spread Operator(...)

Introduced with ES2015, this operator is just great because it is so short and simple. It ‘spreads’ out all of the values into a new object. You can use it as follows:

const obj = {
  age: 21,
  job: "standard file format and data interchange format",
  location: {
       city: "New York",
  },
  name: "JSON",
}

const copyObj = {...obj}

copyObj.job = "nothing"

console.log(obj, copyObj)

/*

{
  age: 21,
  job: "standard file format and data interchange format",
  location: {
       city: "New York",
  },
  name: "JSON",
}

{
  age: 21,
  job: "nothing",
  location: {
       city: "New York",
  },
  name: "JSON",
}

Enter fullscreen mode Exit fullscreen mode

However, much like with Object.assign(), the spread operator only makes a partial copy. So any object with a nested object will not be deeply copied.

Lodash cloneDeep()

Lodash is a modern JavaScript utility library delivering modularity, performance & extras. Lodash also provides a utility method _.cloneDeep() for deep cloning of objects in JavaScript.

const deepClonedObject = _.clonedeep(originalObject);
Enter fullscreen mode Exit fullscreen mode

You can learn more about this and its methods from
https://lodash.com/docs

Conclusion

As you've seen, there are many ways to copy a variable in JavaScript. None of them is perfect for every occasion, so you'll have to be careful to choose the best method for each situation.

Discussion (1)

Collapse
frankwisniewski profile image
Frank Wisniewski

I use the global structuredClone method...

let clone = structuredClone(user)
Enter fullscreen mode Exit fullscreen mode