Immutable Data: Objects

Photo by Joan Gamell on Unsplash

Immutable Data: Objects

A JavaScript approach

Immutability in JavaScript is a not trivial and quite complex topic for many new programmers.

So in order to shed some light on the matter, I wrote a quick guide on object immutability. But first we need to define what is immutability in the JavaScript realm.

By definition, immutability is something that can not change, that remains the same no matter what. We can easily create immutable primitives by using the const reserved word:

const myNumber = 1
const myString = "Hello"
const myBoolean = true

This will create variables that will throw an exception whenever we try to mutate them:

Uncaught TypeError: Assignment to constant variable.

The tricky part comes with arrays and objects, as these are data structures that hold references. For this article, I will center on objects.

We can try to create an immutable object the same way that we created the constant primitives:

const object = {
    id: "object"
}

For sure, we can try to change a property and it will not let us:

object.id = "new object"

Wait… what happened in here? The object now has a different id:

{
    id: "object"
}

The first thing that we need to understand is that we created an “immutable” object. The object reference is constant and if we try to change it, it will throw an exception:

object = {
    id: "other object"
}

Uncaught TypeError: Assignment to constant variable.

The second thing that we need to understand is that an object holds references to other things, like primitives, arrays, or to other objects, and these references are not immutable by default.

There are ways to restrict the access levels on objects, such as Object.freeze, Object.seal and Object.preventExtensions, but I am going to talk about them in a later entry.

Without restricting the access level to an object, we can surely work with immutability, or at least with the concept.

But why do we want to work with immutable objects, if is easier to just update an object and continue our lives?

Simple; if we work with objects that do not change through the application, we eliminate the possibility of updating and object by mistake. Also, if you are working with functional programming, Immutability is a must.

The idea behind these Immutable objects is, instead of changing the properties of an object, create a new object with the properties that you need in the object, plus the properties that you want to update, minus the properties that you do not want in your new object.

So here is a small guide on how to work with “immutable” objects if you do not know how to restrict access to the object.

Create an object

  • Declare an object with properties

Input:

const object = {
    id: "object",
    prop1: "Property 1"
}

Output:

{
    id: "object",
    prop1: "Property 1"
}

Add/Modify properties in an object

  • Use the spread operator to get all original object properties
  • Declare properties that you want to modify, these will take precedence over the original object properties
  • Declare new properties if needed

Input:

const updatedObject = {
    ...object,
    prop1: "Updated property 1",
    prop2: "New property"
}

Output:

{
    id: "object",
    prop1: "Property 1",
    prop2: "Property 2"
}

Remove properties from an object

  • List all properties that you want to remove from object
  • Use spread operator to group the remaining properties into a new object

Input:

const {prop2, ...objectWithoutProp2} = updatedObject

Output:

{
    id: "object",
    prop1: "Property 1"
}