A portrait of Alex Turner
13 Apr, 2023 4 min read

Functional JavaScript

Functional JavaScript - Steadfast Collective Walk Through The Reasons Why Functional Programming Is A Popular Approach To Coding
Functional JavaScript

We believe that to be a good developer, we should always be learning. Something I have been exploring and getting to grips with is functional programming.

Functional programming has been gaining popularity in recent years, and for good reason. It's a programming paradigm that focuses on writing code that is easier to reason about, more predictable, and less prone to bugs. JavaScript as a language supports functional programming, and there are many libraries and frameworks that are built on this paradigm.

In functional programming, functions are treated with more importance. This means that they can be assigned to variables, passed as arguments to other functions, and returned as values from functions. This makes it easy to write modular, composable code.

One of the biggest advantages of functional JavaScript is that it makes it easier to reason about your code. When you write code using functional programming principles, you're essentially breaking down your code into small, composable functions that each do one thing well. This makes it easier to understand what your code is doing and to debug it if something goes wrong. It also adheres more closely to the Single Responsibility Principle, a key programming concept. If each function is only concerned with one simplistic task, it reduces risk. Especially as your program grows.

When you write code using functional programming principles, you're essentially writing code that is "stateless". This means that your functions don't rely on any external state or side effects to produce their output. This makes it easier to test your code and to reason about how it will behave in different scenarios.

const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(num => num * num);
console.log(squaredNumbers); // Output: [1, 4, 9, 16, 25]

Above is a simple example. We are defining an array of integers 1- 5. We then define squaredNumbers method in the functional style; by assigning this map of the numbers array to its own variable, we are not mutating the data. 'Immutability' is an important facet of the paradigm as it means we are not causing unwanted side effects that we might not be expecting. We can output the result of squaredNumber as much as we like and the outcome will be reliably be the same.

Functional JavaScript also makes it easier to write concurrent code. Since each function is stateless and doesn't rely on any external state, you can run multiple functions at the same time without worrying about race conditions or other synchronisation issues.

Here's an example. Let's say we have an ecommerce website that needs to retrieve data from multiple APIs before displaying the page to the user. We want to retrieve data about the user's shopping cart, their shipping address, and the items in their cart, and we want to do all of that at the same time to reduce page load speed.

function getCartData(userId) {
  return fetch(`https://api.example.com/cart?userId=${userId}`)
    .then(response => response.json());

function getShippingAddress(userId) {
  return fetch(`https://api.example.com/shipping?userId=${userId}`)
    .then(response => response.json());

function getCartItems(userId) {
  return fetch(`https://api.example.com/items?userId=${userId}`)
    .then(response => response.json());

]).then(([cartData, shippingAddress, cartItems]) => {
  // Render the page with the retrieved data

Each function responsible for getting those pieces of data is a stateless promise. Now what does that mean? A promise is essentially a stand-in for a value that ultimately will be resolved in time. Meaning we can call the function handler before the value is known (asynchronously). Which allows us in Promise.all to begin the process of collating the data. Secondly, stateless again here, meaning that each function does not rely on any other states within the codebase. This stops us having to worry about any other condition in the code not being met, preventing the function being executed.

This was initially a confusing approach to coding (especially coming from an object-oriented background), but it has really made my code more fluid. It also improves the ability to take advantage of asynchronicity, and it's easier to debug. I highly recommend incorporating this into your code!