Things you should know about Objects and Immutability in JavaScript
Summary
Most things in JavaScript are objects, and while mutability is not inherently wrong, its misuse can cause side effects since assigning an object to a new variable only passes a memory reference, modifying the original.
Immutability maintains object state by creating a new object with updated data instead of changing the existing one, making code simpler, traceable, testable, and less prone to side effects.
Pure functions combined with the Objects API, ES6 destructuring, or methods like .map, .filter, and .reduce are recommended approaches to create immutable objects.
Libraries such as ImmutableJS, Freezer, and seamless-immutable support immutability, and Redux with ImmutableJS is used to build pure and functional front-end projects.
As a JavaScript developer, we should know that most things are objects – from core features, like strings and arrays, to the browser’s APIs. Here you can have a full introduction about objects in JavaScript.
JS’s objects are so beautiful: we can copy them, change and remove properties and do many cool things.
However, it’s always good to remember:
What’s wrong with mutability?
That’s a question many developers have, and here a reasonable answer: there is nothing wrong if the code is mutable – the JavaScript’s Array API is and there’s nothing wrong with that. Yet, the misuse of mutability can cause side effects to your software. Here’s an example:
const user = {
name: 'John Due',
birthdate: '1988-08-15',
}
const changeName = (user, newName) => {
const newUser = user
newUser.name = newName
return newUser
}
const userWithNewName = changeName(user, 'Jojo')
// both users will have the name = 'Jojo'
console.log(user, userWithNewName)
We can see that: although we are creating a new object, the user one was modified. This happens because when you assign a new value to an existing object, you are just assigning a memory reference to it.
const newUser = user
Come to the Immutable side of the force
Immutability is the art of maintaining the state of an object, making development simple, traceable, testable and decreasing any possible side effects. The main idea is: an update should not change the object, but create a new object with the updated data.
We can achieve immutability through pure functions, aka functions that will always return a given value if provided with the same input values. Neat, right? See this example:
const user = {
name: 'John Due',
birthdate: '1988-08-15',
}
const changeName = (user, newName) => {
return {
...user, // destructuring user object
name: newName, // override name attribute with new name
}
}
const userWithNewName = changeName(user, 'Jojo')
// the old user object has name = 'John Due' and the new object, name = 'Jojo'
console.log(user, userWithNewName)
Here we have a user object and its changeName function. You can see that, given the initial user and the new name, the initial object isn’t updated, and we always have the same result.
Creating Pure Functions and Removing References
Okay, we already know what can happen if we change the object’s state, now we need to know how to work with objects without causing side effects.
There are some ways to make immutable objects, but the most recommended approach to create them is using the Objects API and the ES6 destructuring assignment. We could also use functions like .map, .filter and .reduce to accomplish the same task.
// Example using Objects.assign
const changeName = (user, newName) => Object.assign({}, user, {
name: newName
})
// Example using destructuring assignment
const changeName = (user, newName) => ({
...user,
name: newName,
})
Wrapping up
When coding with JavaScript, manipulating objects is simple and practical, even though, it requires some care so your code does not end up bringing you headaches. Always remember to test your code to avoid unexpected mutation of objects.
Here at Cheesecake Labs we use Redux and ImmutableJS to accomplish pure and functional Front-end projects, keeping our code clean and easy to read.
Happy Coding!
share this article
FAQ
What's wrong with mutability in JavaScript?
There is nothing inherently wrong with mutability — the JavaScript Array API is mutable, for example. However, the misuse of mutability can cause side effects in your software. For instance, when you assign an object to a new variable, you are just assigning a memory reference to it, so modifying the 'new' object will also modify the original.
What is immutability?
Immutability is the art of maintaining the state of an object, making development simple, traceable, testable and decreasing possible side effects. The main idea is that an update should not change the object, but create a new object with the updated data.
How can you achieve immutability in JavaScript?
Immutability can be achieved through pure functions — functions that always return the same value when provided with the same input values. The most recommended approach to create immutable objects is using the Objects API (such as Object.assign) and the ES6 destructuring assignment. Functions like .map, .filter and .reduce can also be used to accomplish the same task.
What is a pure function?
A pure function is a function that will always return a given value if provided with the same input values.
Which libraries are mentioned for working with immutability?
The post mentions ImmutableJS, Freezer and seamless-immutable as libraries that work well with immutability. Redux and ImmutableJS are used at Cheesecake Labs to accomplish pure and functional Front-end projects.