Avoiding mutation with Shallow Copy

Marcos Gonçalves
NERDJACKING
Published in
3 min readMay 31, 2021

An approach to save you time and refactoring efforts

JavaScript is beautiful❤️‍🔥 but there is some caveats that you must know about, one of them is about mutation.

Let’s take a deeper dive on this effect and understand once for all what’s that all about on and how you can overcome this effect in an elegant way.

To illustrate the problems, most of the explanations will be covered with some clear examples that you can easily test on your side, even through your Browser’s console.

So enough chit-chat, let’s get straight to the point.

What’s precisely mutation?

Mutation is an alteration of the existing value(s) from a data structure, like Object, Array, Function, Map, Set, so on.

It happens every time you add, remove or modify the initial data state.

Here is some examples of that:

Is there immutable data types?

Yes! All Primitives (primitive values and primitive data type) are immutable by nature, meaning that they cannot be altered.

Example:

The undesired mutation side-effects

As you probably could see, it’s very easy to mutate a data structure and this can easily introduce some undesired side effects, like:

  • Surprises: your code is no longer deterministic but unpredictable.
  • Lost of data reliability: your data is no longer reliable as you cannot be sure if it’s still pure.
  • Increased maintainability cost: you have to spend more time to refactor/maintain your code just because you got surprises around the way.
  • Bugs: well, this is the result of all the points above.

Let’s take a look on an real world undesired side-effect caused by mutation:

The method maskSensitivityInfos() not only mutated the credit card number, introducing a new bug, but also broke the entire payment processing pipeline of the application; and I’m pretty sure that someone would be not reeeally happy about it.

Fixing mutation

This is a fairly easy task! All we got to do is to copy the Object.

This can be done either by using Spread Operator or Object.assign().

Tip: learn to take advantage of ES6 ‘spread operator’

With just a small tweak we not only fixed the example above but made it reliable again!

The only tricky part is, copy process can vary from data-structure to data-structure, example:

  • Copy Array: const copy = [ ...originalArray ]
  • Copy Object: const copy = { ...originalObject }
  • Copy Date: const copy = new Date(originalDate)
  • Copy Map: const copy = new Map(originalMap)
  • Copy Set: const copy = new Set(originalSet)
  • so on…

To avoid those repetitive operations (code duplications) we can take advantage of the Shallow Copy approach.

Shallow Copy

Shallow Copy is a code utility that centralize all copy related operations into a single place and takes care of the different copy strategies required from the data structure.

This approach has some great benefits, like:

  • Single source of truth.
  • Low refactoring effort required.
  • Reusability.

Just be aware that, as a shallow operation, this only affects the first level of the structure, meaning that anything bellow the 1st level, will be unaffected.

This will generally satisfy almost all your needs, but in case you need to have a deep copy, you can easily update the code to include a recursive operation over its items 😉

Dependency

We will be using an improved version of the JavaScript typeof() operator, which we covered here before, if you haven’t read it yet, click in the link bellow and check that out!

Formulas

ES6

Typescript

Got something on your mind? Let us know in the comments 💪

--

--

Marcos Gonçalves
NERDJACKING

Lead Engineer | Architect | Developer Advocate | 12+ years of experience. Also a lover of a good beer in his spare time.