Javascript – favour immutable patterns

I am going to use quite a basic example here, but I feel it still gets the point across, consider this code:

the person object is being created with department: ‘IT’ because if the getEmployeeDepartment is not able to find their department, then it should remain as IT, this is the default. There is a problem here though. Consider these three lines of code inside our loop:

At a glance it might seem like with each iteration we are starting with a fresh person using the default state of the original person object, then only mutating the newly created personToUpload. But we are not…

when we write:

we are actually creating a new variable in memory that is also a reference to the original person object. The problem with this is, with each iteration of our loop, we are mutating the original object. If it isn’t obvious why is is bad, consider this scenario:

Our uploadPersonData function is passed an array containing 3 employee Ids. when we run our logic for the first employee, we resolve a department of “HR”, when we run our logic for the second employee, we resolve a department of “”, and finally when we run our logic for the third employee, we resolve a department of “Product”. Remember that we said earlier that, if no department was resolved, we would stick to the default of department: “IT”. So what do we expect the three personToUpload variables to have looked like, well if everything was working correctly we would expect it to be:

But this isn’t going to be the case, what we will actually end up with is:

Why is this? Well the problem is that, in our first iteration when we set the department of “HR” for the first employee, we actually mutated the original person object in memory. So in our next iteration when we were not able to resolve a department, remember that empty string is falsy, and we did not set it, we just ended up with that same value of “HR”. The third iteration was fine because we did set the department there, so it paved over the cracks, so to speak.

How can we fix this? Well let’s look at a more immutable approach. When we create the personToUpload for each iteration we can simply do this instead:

and problem solved. We are now working with a reference to an entirely new object in memory, and in this scenario when we mutate any of the personToUpload properties, this will not effect the original person object, it can remain as a default shape.

Please note that in certain circumstances even with this pattern you may still end up with a new object that contains references to deeper parts of the original object, see this article on deep vs shallow cloning.