DEV Community

Antonio Pangallo
Antonio Pangallo

Posted on

Best practices to keep objects and arrays immutable in javascript.

Immutability

Immutability is a core principle in functional programming. In this post, I am going to list some of the best practices used to keep data structures immutable in JavaScript without using any third-party libraries.

Which data types are immutable in Javascript then ?

Primitives data types like string, number and boolean are immutable by default, they cannot be altered so you do not need to apply any "magic" to keep them immutable. We cannot say the same for objects and arrays which are mutable by default, because they are only references.
Following, We will go through some operations that will help us to keep also objects and arrays immutable.

Operations on arrays.

Cloning an array of primitive data types.

const sourceArray = [1,2,3];
const clonedArray = [...sourceArray];
// or you can do
const clonedArray = sourceArray.slice(0);
Enter fullscreen mode Exit fullscreen mode

Cloning an array of objects which props are primitive data types.

const sourceArray = [{ a: 1}, { b: 2 }, { c: 3}];
const clonedArray = sourceArray.map(item => ({...item}));
Enter fullscreen mode Exit fullscreen mode

Adding an new element into an array.

const sourceArray = [1,2,3];
const newArray = [...sourceArray, 4];
const sourceArray = [{ a: 1}, { b: 2 }, { c: 3}];
const newArray = [...sourceArray, { d: 4}];
Enter fullscreen mode Exit fullscreen mode

Removing an element from an array.

const itemToRemove = 3;
const sourceArray = [1,2,3];
const newArray = sourceArray.filter(item => item !== itemToRemove);
Enter fullscreen mode Exit fullscreen mode

Replacing an element into an array.

const itemToAdd = { id: 2, a: 4 };
const sourceArray = [{id: 1, a: 1}, {id: 2, a: 2}, {id: 3, a: 3}];

// replacing without caring about position
const newArray = [...sourceArray.filter(item => item.id !== itemToAdd.id), itemToAdd];

// replacing caring about position
const indexOldElement = sourceArray.findIndex(({ id }) => id == itemToAdd.id);
const newArray = Object.assign([...sourceArray], {[indexOldElement]: itemToAdd});

// or you can do
const newArray = [...sourceArray.slice(0, indexOldElement), itemToAdd, ...sourceArray.slice(indexOldElement + 1)]
Enter fullscreen mode Exit fullscreen mode

Operations on Objects.

Adding a new prop.

const sourceObj = { a: 1, b: 2};
const newProp = { c: 3 };
const newObj = { ...sourceObj, ...newProp};
// or you can do
const c = 3;
const newObj = { ...sourceObj, c};
// newObj = { a: 1, b: 2, c: 3};
Enter fullscreen mode Exit fullscreen mode

 Removing a prop.

const sourceObj = { a: 1, b: 2, c: 3};
const { b, ...newObj } = sourceObj;
// console.log(newObj) => { a: 1, c: 3};
Enter fullscreen mode Exit fullscreen mode

Update a nested Object which props are primitives.

const sourceObj = { a: 1, b: 2, c: { d: 3, e :4 } };
const c = { ...sourceObj.c, f: 5 }
const newObj = { ...sourceObj, c };
Enter fullscreen mode Exit fullscreen mode

Update a nested Object which props are not primitives.

const sourceObj = { a: 1, b: 2, c: { d: [1, 2, 3 ], e :4 } };
const d = [ ...sourceObj.c.d, 4 ];
const c = { ...sourceObj.c, d }
const newObj = { ...sourceObj, c };
Enter fullscreen mode Exit fullscreen mode

Unfortunately, the process of correctly applying immutable updates to nested object can easily become verbose and hard to read.

Few words on performances?

Creating a new object is more expensive in term of time and memory consuming, but these disadvantages are smaller then advantages in so many cases.

Advantages like being able to fast compare two immutable objects relying only on the identity/strict equality operator check oldObject === newObject, or reducing the possibility of nasty bugs, which might happen, in applications that shares data structures across different components is something that you should think about before starting coding.

Conclusion

If you are currently using or learning any library based on immutability all the operation described above can help you. I hope you enjoyed reading this short post, feedbacks are welcome!

Top comments (0)