Immutability in Array of objects, using Map method

Sašo Sabotin
Frontend Weekly
Published in
3 min readDec 26, 2017

If this article’s title spiked your interest enough to open it, then I must assume you know about how Array.map is implemented. It clearly states, that map method is not going to mutate the existing array, but it rather creates the new array of mutated data. Everything works as expected until it comes to the array of objects, which technically is working as expected as well.

“You must be wrong, it does not work for me though!” is what you are thinking right now. Am I right?

Let’s say, that we have an array of objects which looks like this:

Each event item has its own name and some metadata, where the type of the event is specified. In order to mutate this array of objects, we have multiple approaches. But essentially you have to loop through the array of items and modify its state.

To achieve that, I am normally using array’s map method implementation which accepts the callback function as the parameter, where all the magic happens.

Mutating the object is mutating the original array

The map method is looping through the array of items, which are in our case Javascript objects. To change the object item, we normally mutate the actual item’s properties and return it as a new item, which is working as expected. But the problem is that the original array of objects is also going to be mutated.

Why is original array’s data mutated as well?

The map method is cloning the array as it is intended to do, but since we have an array of objects, each item is actually only a reference to the object in memory. This means, it is essentially cloning the object’s reference, which will point to the same block in the memory as the original array’s objects.

So when we are changing the properties of the object in the callback method, we are actually changing the properties via reference, which will mutate the original object as well. Since the object’s reference is located in the original array, we will also see the changes in the original array.

Mutating the object without changing the original array

If you want to make changes only in the cloned array of objects and not in the original one, there is a way to do it.

The basic idea is to create a new empty object for each item in the array and assign the properties from old objects to them, respectively. This means we get an object with a new reference, so we are not going to modify the old one anymore.

Creating a new object and assign the properties

To achieve that, we can use Object.assign() method, or from ES6 update on, we can use spread operator {...}, which will do that for us.

The code below will now create a new object with the value of the name property modified.

const newObject = {...oldObject, name: 'Modified name'}

Let’s try it with real example

You have seen the array of objects which is going to be our example array. So this is what we are going to do:

  1. Loop through events, using Map method,
  2. make a condition, to find the Event 2 event by name,
  3. modify the object’s properties with help of the spread operator {...}.

In line 22, you can see that we are overwriting the original object with a newly created one and with the modified name to Second Event.

It works! But why do we modify the metadata in the same way? Isn’t that cloned as well?

You got the point! It is cloned, but still only the reference to the object. So even though we have cloned the whole object and created a new reference, we still have an object inside of an object, which is holding its own reference. The reference to this object is again located in the old array, therefore we have to create a new reference for that object if we don’t want to make changes to the old array.

You can find the solution, of how to create a new object and assign the new metadata properties to it, in line 23.

Having a lot of nested objects will make cloning of the object a lot more difficult!

I wish this article was helpful to you, so you don’t have to debug the Map method for hours! :)

--

--