Immutability
The first thing to know about functional programming is Immutability.
What is it?
At the core its goal is to make change impossible where you do not expect it.
A problem that developers often run into is that they cannot tell where a variable has changed, or aren’t certain how a value came to be. Now you might think that it is not an issue, and perhaps for small progams it isn’t, but once there are many people working on software over years things are not so simple. Once features have been reworked by different teams and developers it is nice to be assured you know exactly what is happening to your variables at any point in time.
The Pros
- You 100% know the state of your code at any point, as variables cannot be changed after they are initially set. This includes 3rd party libraries, where you don’t have to worry about functions changing your objects.
- The code is more maintainable - It is always good to think about people in the future looking after you code.
The Cons
Like most things, there are situations where the concept doesn’t work and in these cases it might be best to use mutable variables instead.
- Performance - There is a small performance cost to creating many immutable structures rather than a single mutable variable.
- Some data structures are much harder to create.
The Syntax
There are two different types of syntax used in javascript for immutability. One is for primitives and references, and the other is for object properties. We will assume all code in this article is in strict
mode.
How to use
Below I have details some common problems that use mutations and how they can be achieved with immutable code.
Finding elements of an array
How to start with an array of items, and remove any that do not match the criteria you are looking for.
let fruits = [
{ type: 'Apple', nice: true},
{ type: 'Banana', nice: false},
{ type: 'Mango', nice: true}
];
// This is bad practice in general, at it changes
// and array as we are iterating it.
fruits.forEach((fruit, index) => {
if (!fruit.nice) {
fruits.splice(index, 1);
}
})
const fruits = [
{ type: 'Apple', nice: true},
{ type: 'Banana', nice: false},
{ type: 'Mango', nice: true}
];
const niceFruits = fruits.filter((fruit) => !fruit.nice);
Removing keys from an object
It is common to want to return only a subset of the data you have from your API. This is probably best done by tools such as GraphQL, $project
in mongodb, SELECT
statements in SQL, but it is not uncommon to do the same thing in code.
function removeKeyFromObject(key, obj) {
delete obj[key];
}
const user = {
username: "my-username",
password: "secret",
};
removeKeyFromObject("password", user);
// user = { username: "my-username" }
function removeKeyFromObject(key, obj) {
const {[key]: propToDelete, ...newObj} = obj
return newObj;
}
const user = {
username: "my-username",
password: "secret",
};
const userWithoutPassword
= removeKeyFromObject("password", user);
// userWithoutPassword = { username: "my-username" }
What to read more? Check out more posts below!