Functional Programming Principles in JavaScript

Functional Programming Principles in JavaScript

Featured on Hashnode

Subscribe to my newsletter and never miss my upcoming articles

The art of problem-solving using... functions!

Functional Programming is a programming paradigm that relies on the use of functions whether they are pure or isolated functions, avoiding changing-state and mutable data. In general, the use of functional programming breaks the program into small parts, which helps the developer to test it (bug prevention!!!) and to build more complex codes by combining the functions - and reusing them!

In this article, we will explore the principles of Functional Programming, which is a fabulous paradigm to use when building software! 🤩

Types of Functions

First-Class Functions

When we talk about JavaScript, all functions are first-class functions, which means we can use them like any other value. In other words, they are functions that are able to be passed as arguments to other functions, returned as values from other functions, stored in data structures, and assigned to variables.

const multiply = (a, b) => {
    return a * b;
}

const multiplier = multiply;

multiplier(2, 10); // 20

Higher-Order Functions

In JavaScript, it is possible to have functions that accept others functions as an input or we can return a function from another one as an output. This is the definition of higher-order functions!

Some well-known exemplars are filter(), map(), sort() and reduce().

const animals = ["lion", "tiger", "whale", "shark", "horse"];

const filteredAnimals = animals.filter(animal => animal.includes("a")); 
// ["whale", "shark"]

Pure Functions

The main idea of pure functions is the same as the mathematical definition of a function: y = f(x) is an equation where the x is the input and y the output. The result of this equation will be always the same for the same input.

In JavaScript, we have some examples of pure functions: size(), strlen(), pow(), sqrt(), where if you pass the same argument, you get the same output every single time. The map() method is another example - it does not change the original array; instead, it returns a new one!

In the case of the Math.random() or Date.now(), each time we call it, the output will be different:

Math.random(); // 0.20254012076359018
Math.random(); // 0.5509985197955656

Date.now(); // 1607746557125
Date.now(); // 1607746557890

So, they are not pure functions, neither is pop(), which directly removes an item from the end of an array, nor splice(), which allows you to take a section of an array (and many other functions!).

In fact, pure functions help us to have a clean code where you don't use global variables, and it is the basis of Functional Programming. But there are other benefits that we must take into account, so let's summarize:

  • Always return the same result if given the same arguments;
  • Do not cause any side effects - for example, mutating some global variables, the parameter passed by reference or even IO.
  • Easy to test each isolated function, without the needing of mock anything;
  • Avoid concurrency when using threads for each operation;
  • Memoized results that can be cached and reused;
  • Declarative programming, once it describes exactly the inputs required.

Principles of Functional Programming

Side Effects

Side effects are everything that changes the current state of the program - in other words, what affects the environment that is outside the function. For instance some examples of side effects, but it is not limited to:

  • DOM updates;
  • Fetching requests;
  • Logging to console;
  • Changing (mutate) an external variable;
  • Writing to a file;
  • Spawn a process;
  • Saving data in a database.

Wait! Functional Programming does not say that you cannot have side effects, because sometimes we need them or it is impossible to get rid of them. But the idea is to reduce the occurrence as much as possible!

Immutability

Immutability refers to preventing the state from being modified, even if it is a reference mutation or value mutation. Before going deep in the concept, it is important to discuss that Functional Programming avoids some language constructs, which are:

  • Loops (while, for, etc);
  • Variable declarations using var or let;
  • Void functions;
  • Object mutation;
  • Array mutator methods;
  • Map mutator methods;
  • Set mutator methods.

In JavaScript, primitives such as undefined, null, boolean, number, string, and symbol values are immutable by default, so you are already prevented from permanently altering primitive values themselves.

An example using string:

const str = "hi guys";

str[0] = "l";

console.log(str) // "hi guys";

Values such as objects or arrays can be assigned by reference. It is an example of a mutation, which Functional Programming avoids.

let array = ["hi"];
let ref = array;

ref.push("guys");

console.log(array, ref); // ["hi", "guys"], ["hi", "guys"]

Immutability ensures your code is decoupled, as it allows you to control how objects in your system are allowed to be changed. But it is not that easy - in contrast, you may need to clone the entire object with the changes you need, and it is costly to the application most of the times. 😰

JavaScript has some native mutator methods which we must be aware of when developing. While the slice() method is a pure function, the splice() method is not, as it returns a different value every time we call it and changes the value of the original array.

const array = ["hi", "guys"]

array.slice(0,1); // "hi"
array.slice(0,1); // "hi"

console.log(array); // ["hi", "guys"]

array.splice(0,1); // "hi"
array.splice(0,1); // "guys"

console.log(array); // []

Other mutator native methods are:

  • Array mutator methods: copyWithin(), fill(), pop(), push(), reverse(), shift(), sort(), splice(), unshift();
  • Map mutator methods: clear(), delete(), set();
  • Set mutator methods: add(), clear(), delete().

In fact, every mutator method can be replaced by a function that returns a new array, Map or Set with the desired changes! 😄 And voilà, you are using the ideas of Functional Programming!

Thank you all for reading this article, and see ya in the next post ;)

 
Share this