Is spread operator for object cloning in javascript always immutable?

Is spread operator for object cloning in javascript always immutable?

#Javascript #mutable #coding #cloning #object

We all use spread operator in javascript to create clone(shallow copy) of object or array. As we create shallow copy using spread operator, any change in cloned copy must not change in the original copy of the data. Let us understand with one example.

const book={
    name: "Lost Mind",
    page: 300,
    author: "XYZ" 
}

const temp={...book};
temp.page=400;
// Book.Page: 300
console.log("Book.Page: ", book.page);
// Temp.Page: 400
console.log("Temp.Page: ", temp.page);

From above code it is easily understandable that, we first created a book object with name, page & author property. Then using spread operator, we have cloned(shalow copy) the book object in temp variable. Now, we are changing page property of temp object from 300 to 400. As we have created shalow copy of book object, the above change in page property will be only reflected in temp object & not in book object.

Does this always work?

Let's consider an example to check if this always works or not.

const book={
  title:"Rebirth",
  publisherName:"XYZ",
  publishYear:"2022",
  pages:200,
  author:{
    name:"ABC",
    age:55,
    contact:{
      email:"abc@abc.com",
      phone:"9999999999"
    }
  }
}

const temp={...book};
temp.author.contact=null;

// Book.Author.Contact:null
console.log("Book.Author.Contact:",book.author.contact);

//Temp.Author.Contact:null
console.log("Temp.Author.Contact:",temp.author.contact);

So, in the above example we have created a book object(Nested Obiect) with title, publisherName, publishYear, pages & author property. Here author property holds an object type data which contains name, age & contact property. Now we cloned(Shalow copy) that book object into temp variable using spread operator. Now, if we change author.contact of temp variable to null, it should only update author.contact in temp variable & not in book variable. But in reality, this is not true. As we can observe, if we log author.contact of both the variable, then it will log null for both.

Why this happens?

Actually only the primitive data types won’t get mutated by default when we clone using spread operator.

What are the premitive data types in Javascript?

In JavaScript, a primitive (primitive value, primitive data type) is data that is not an object and has no methods or properties. There are 7 primitive data types:

  1. String

  2. Number

  3. BigInt

  4. Boolean

  5. undefined

  6. Symbol

  7. null

Explalation for above example

As, temp.author is pointing to the same memory location as book.author. So, any change in any property of temp.author object will change in the same memory location as book.author. If we update temp.author.age to 60 then book.author.age will also be 60.

But if we update temp.author to null, then it will not be reflected in book.author. So, only temp.author will be null but not book.author.

Then what is the solution?

Let's understand with an example-

const book = {
  title: "Rebirth",
  publisherName: "XYZ",
  publishYear: "2022",
  pages: 200,
  author: {
    name: "ABC",
    age: 55,
    contact: {
      email: "abc@abc.com",
      phone: "9999999999"
    }
  }
}

const temp = { ...book, author: { ...book.author, contact: { ...book.author.contact } } };
temp.author.contact = null;

// Book.Author.Contact: {
//      email: "abc@abc.com",
//      phone: "9999999999"
//    }
console.log("Book.Author.Contact:", book.author.contact);

//Temp.Author.Contact:null
console.log("Temp.Author.Contact:", temp.author.contact);

For non primitive data types, it is neccessary to apply spread operator for every level of nesting to deep clone the object. Now, we have successfully deep cloned the object without mutating it. But if our object is very deeply nested, it will be painful to clone it this way. There is no other straight forward solution in Javascript either.

Hope you enjoyed and learnt one of the essential trick in JavaScript 😎