This content originally appeared on Bits and Pieces - Medium and was authored by Fernando Doglio
The benefits and how-to of immutable data structures

Immutability is the state in which nothing changes, nothing “mutates” and we can map that concept when speaking about coding, to data structures never changing.
How is that possible and why would you want to do that? Those are two very good questions that I’m going to try to explain in this article. Hopefully by the end of it, you’ll have the tools to decide when to use them and when not to.
Alright, but what exactly are immutable data structures?
As I mentioned, these are structures that never change, even if you think they are, internally a new version of it is being created.
One great example of that is the String type in JavaScript, you see, Strings are immutable.
For example, when you write:
let myStr = "Hello "
myStr += " World"
While you might think that you’re only dealing with a single string, you are, in fact, dealing with two. And the easiest way to validate the immutability of strings is to try and replace a character using the square brackets notation:
This is why all string methods actually return a new version of it, instead of replacing the original one. For example:
Other data structures, like arrays, for instance, are not immutable though, and that’s why it’s important to understand the difference.
Why is it important to have immutable data structures?
The first thing to note though, is that while immutable data structures are great for some situations, they’re not ideal for ALL use cases, so the key here is to understand that they’re a tool you can leverage, not that you have to change the way you work from now on.
With that said, the main benefit of working with immutable data structures is that they provide consistency. In other words, they remove the ability for you to unwillingly modify a value that’s shared amongst many functions and cause a potential side effect without even trying.
For example, let’s take a look at the following example:
In the example, we have a mutable list that gets passed as a parameter into two different functions. These functions are randomly executed one after the other (you don’t really know the order in which they run). These functions perform their own operations on top of the data structure without considering the other function (as they should). And finally, the original mutable data structure is printed out.
As you can probably guess, the random factor will cause the script to print out different results if you execute it multiple times. That alone is already a bad omen, since ideally our code should be deterministic, meaning that if executed under the same conditions it should always produce the same output.
Now, another similar example that might also be useful to show the perils of dealing with mutable data structure, is the following:
It’s the same structure as before, but now we have a clear function that is performing changes on a mutable structure, and another function that relies on the data to produce a result. This example clearly shows the problem of side effects.
If you think about it, that can be frustrating to deal with in a real-world scenario because you’re not using global variables inside your functions. You’re supposed to be doing everything fine, however, if the change1 function gets executed first, the output of sumValues will be 12, while if it gets executed second, the output will be 6.
So you’ll either get the following wrong output:
The sum of the doubles is: 12
The sum of the original numbers is: 12
[ 2, 4, 6 ]
Or this:
The sum of the original numbers is: 6
The sum of the doubles is: 12
[ 2, 4, 6 ]
Which, even though the last line shows the list having been changed, at least the first line is correct.
And while there might be ways to solve this, the underlying issue here is that you’re dealing with a mutable data structure and you either don’t care, or you just don’t know and you’ve added a potential bug into your system. Not only that, but a random bug at that (ugh, I hate those), which makes it exponentially more difficult to debug.
So the main reason why you want to use immutable data structures whenever you can, is because they remove your ability to unwillingly add side effects to your code, thus reducing the number of bugs you might have on your system.
If you liked what you’ve read so far, consider subscribing to my FREE newsletter “The rambling of an old developer” and get regular advice about the IT industry directly in your inbox.
Using ImmutableJS to add support for immutable data structures to JavaScript
While this is not strictly necessary, adding an external library like ImmutableJs can simplify the task of only using immutable structures.
The beauty of this particular library is that it adds immutable replacements (amongst other things) to all mutable data structures available in JavaScript. So if you add this library to our previous example, like this:
Notice that all I did was change line 3 by creating a List with my original Array. Now the output is this:
The sum of the original numbers is: 6
The sum of the doubles is: 6
This is not what I was expecting, but it’s not wrong! In fact, it’s doing exactly what I wanted, it’s not even letting me modify the original array inside my change1 function. I’m forced to create a new array, I have no other choice. I can now see that using the map method would help me, since both the original and the immutable versions produce a new list as a result. So I can change my change1 function to be:
This is all the change I needed. Granted, I could’ve done this without ImmutableJS and the result would’ve worked as well, but thanks to the library I found the solution.
Let’s go back to the change1 vs change2 example, in which both functions were pushing values into the same array. We can also fix that issue simply by adding ImmutableJS into the mix and declaring the original array as a List :
Of course, the output from this script will not be what we expect it either, can you guess why?
Here is what we get:
List {
size: 0, <-------
_origin: 0,
_capacity: 0,
_level: 5,
_root: undefined,
_tail: undefined,
__ownerID: undefined,
__hash: undefined,
__altered: false
}
List {
size: 0, <-------
_origin: 0,
_capacity: 0,
_level: 5,
_root: undefined,
_tail: undefined,
__ownerID: undefined,
__hash: undefined,
__altered: false
}
List {
size: 0, <-------
_origin: 0,
_capacity: 0,
_level: 5,
_root: undefined,
_tail: undefined,
__ownerID: undefined,
__hash: undefined,
__altered: false
}Those are the 3 console.log I have on my script. Ignore the structure of the output, since we’re dealing with a more complex object, there is more to print. But look at the three spots I highlighted: all of them are empty.
How can that be?!
Because our immutable list can’t be modified, so the push method is actually returning a new list with the added value. It’s not really adding it to the original list. So let’s make the required adjustments to both our functions:
Especially notice line 9, how I’m not doing list.push(3) but rather myList.push(3) . This is because since the method returns a new structure, the first 3 (on line 8) wouldn’t be present in list on line 9.
The output now, looks like this:
List {
size: 1, <--------
_origin: 0,
_capacity: 1,
_level: 5,
_root: null,
_tail: VNode { array: [ 2 ], ownerID: OwnerID {} },
__ownerID: undefined,
__hash: undefined,
__altered: false
}
List {
size: 2, <--------
_origin: 0,
_capacity: 2,
_level: 5,
_root: null,
_tail: VNode { array: [ 3, 3 ], ownerID: OwnerID {} },
__ownerID: undefined,
__hash: undefined,
__altered: false
}
List {
size: 0, <--------
_origin: 0,
_capacity: 0,
_level: 5,
_root: undefined,
_tail: undefined,
__ownerID: undefined,
__hash: undefined,
__altered: false
}The first two lists are individually modified and the last one remains intact.
Why would you not use immutables for everything?
As I said before, immutables are not ideal for every use case. As you can probably imagine, creating a new data structure every time we want to modify a list, or a set or anything that is mutable can have a performance impact.
Now, don’t go and understand that statement incorrectly. I’m not saying immutability is not performant. In fact, several algorithms allow for libraries like ImmutableJS to create new structures on the fly quite fast.
That said, in extreme cases like game development, where every microsecond counts, it might be worth it to explore other ways to reduce side effects and to learn how to deal with mutability.
But other places, like front-end development, are ideal for immutable structures. In fact, frameworks like React take advantage of this to easily deal with the mutable state of components to understand when it changes and how to trigger the right re-renders.
So don’t ignore the power of immutable structures, just make sure you’re using them properly and within the proper context.
Build composable web applications
Don’t build web monoliths. Use Bit to create and compose decoupled software components — in your favourite frameworks like React or Node. Build scalable and modular applications with a powerful and enjoyable dev experience.
Bring your team to Bit Cloud to host and collaborate on components together, and speed up, scale, and standardize development as a team. Try composable frontends with a Design System or Micro Frontends, or explore the composable backend with serverside components.

Learn more
- Building a Composable UI Component Library
- How We Build Micro Frontends
- How we Build a Component Design System
- How to build a composable blog
- The Composable Enterprise: A Guide
- Meet Component-Driven Content: Applicable, Composable
The Case for Immutability in JavaScript was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Bits and Pieces - Medium and was authored by Fernando Doglio
Fernando Doglio | Sciencx (2022-05-26T07:13:26+00:00) The Case for Immutability in JavaScript. Retrieved from https://www.scien.cx/2022/05/26/the-case-for-immutability-in-javascript/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.