Brief introduction to functional programming in JavaScript
Chamoda Pandithage
Dec 25, 2023
brief-introduction-to-funtional-programming-in-javascript

Functional programming is an effective programming paradigm. Even when you don't use a functional language like Haskell or Erlang, concepts of the functional paradigm can be very useful to make a code-base more readable, maintainable, reliable, and testable. JavaScript is not the perfect language to learn all aspects of functional paradigm nor I'm trying to teach all concepts here. I'm just trying to show few basic concepts of functional programming that you can use to make your code-base better.

So what is functional programming?

Functional programming is where programs are constructed by composing and applying functions. Here's few key principles.

  • Data immutabilty: Data, once created, cannot be changed. Instead of modifing existing data, functional programing encourages creating new data structures with the changes.
  • Pure functions: Functions neeeds to pure without side effects. This will explain later in detail.
  • First class functions: Functions can be assinged to variables, passed as arguments to other functions, and returned as value from other functions.

Three categories in functioanl code

When a functional programmer sees code, they mentally separate the code into three categories.

  • Data: Data is recorded facts with structure.
  • Calculations: Calculations are functions that compute output from output. It does nothing else to code. Functions that only does calculation are pure functions.
  • Actions: Anything that depends on when it runs is an action. When function change a variable outside it's function it's an action. When function send an email the function is an action. Any interaction with UI,dom is an action. If function is an action that function is considered not pure.

See following JavaScript code.

// Here a, b and numbers are data in the code.
let a = 1;
let b = 2;
let numbers = [1, 2];

// Function sum is a calculation.
function sum(a, b) {
  return a + b;
}

// Function increment is a calculation.
function increment(a) {
  return a + 1;
}

// Function increment_numbers is an action. In JavaScript arrays are passed by reference so it modifies the global numbers array which is a side effect.
function increment_numbers(values, amount) {
  for (let i = 0; i < values.length; i++) {
    values[i] = values[i] + amount;
  }
  return values;
}

// Function print is an action. It prints characters into console which is a side effect.
function print(x) {
  console.log(x);
}

Making Javascript code more functional

One of the first things you can do to make your code more functional is minimizing functions in action category. We need actions in our programe to make it usefull, we just need to minimize them as much as possible.

Let's the previous function increment_numbers. It modifies the array numbers directly since arrays are passed by reference to functions. To by preventing this we can make the function a calcualtion function.

// Now this function is calculation function with no side effects
function increment_numbers(values, amount) {
  const values_copy = values.slice(); // Making a shallow copy of the array
  for (let i = 0; i < values_copy.length; i++) {
    values_copy[i] = values_copy[i] + amount;
  }
  return values_copy;
}

You can see that we are making a shallow copy of the array. It it was an object you can use Object.assign({}, obj) to make a shallow copy. If you have a nested array or object you can make a deep copy using new structuredClone(obj) function.

You may think that it's quite wastefull to make duplicate copies like this. In some sence yes, we are recreating objects in memory but they are handled well in Javascript runtimes. You can always optimize later if needed.

Doing this has enoumours benifits to your code base. You can see that it's very eary to test calculation functions. When we increase calcution functions in the code we make our code more testable. No side effects also means less bugs. Also makes the code more readable, maintainable, modifiable.

Stratified design (or layered design)

Stratified design (or layered design) is a technique for building software in layers. Word stratieid coming from latin word stratum which mean layer. This design is very useful to think about how to architecture functions for reusablity and readablity.