DEV Community

Cover image for Javascript: Functional Programming
Kenneth Chévez
Kenneth Chévez

Posted on • Updated on

Javascript: Functional Programming

Functional Programming (FP) is a paradigm used for build computer applications applying and composing pure functions without mutating the state and data. It is also a declarative type of programming that implements the logic of process without explaining its control flow. It makes use of expressions instead of statements.

There's some concepts that are needed to be understood if FP will be applied:

Pure functions

A pure function has two principal characteristics:

1. A function that given the same inputs, return the same output. For Example:

const double = x => x * 2

console.log(double(4)) // 8
console.log(double(4)) // 8
console.log(double(4)) // 8
Enter fullscreen mode Exit fullscreen mode

As you can see, when the function double is called with the same parameter (in this case 4), it always return the same result.

Not all functions fulfill this specification. This are some examples of functions that are not pure:

Math.random() // 0.9475128240189292
Math.random() // 0.1712299774003645
Math.random() // 0.16032971104683935

(new Date()).getTime() // 1620616533928
(new Date()).getTime() // 1620616539849
(new Date()).getTime() // 1620616541638
Enter fullscreen mode Exit fullscreen mode

In this case, the functions random and getTime aren't pure, because given the same parameters are not returning the same value.

2. It has no side-effects. This means that functions are not going to change any arguments, global variables or do some kind of I/O.

const animals = ["cat", "dog", "cow"]

const addSheepAnimal = (animalsArray) => {
  animalsArray.push('sheep')

  return animalsArray
}

const newAnimals = addSheepAnimal(animals)

console.log(newAnimals) // [ 'cat', 'dog', 'cow', 'sheep' ]
console.log(animals) // [ 'cat', 'dog', 'cow', 'sheep' ]
Enter fullscreen mode Exit fullscreen mode

In the example above, the function addSheepAnimal has side effect over the animalsArray parameter, because is changing the array that is pass when the function is called. In order to fix this, the array should be clone inside the function so it has no side effects.

const animals = ["cat", "dog", "cow"]

const addSheepAnimal = (animalsArray) => {
  return [...animalsArray, 'sheep']
}

const newAnimals = addSheepAnimal(animals)

console.log(newAnimals) // [ 'cat', 'dog', 'cow', 'sheep' ]
console.log(animals) // [ 'cat', 'dog', 'cow' ]
Enter fullscreen mode Exit fullscreen mode

Immutable data

Data is immutable when values of javascript structures cannot be changed once are assigned. This means when a variable is already assigned, the value can't be change in coming parts of the flow.

It's a good practice always use const declaration instead of var and let so mutable data can be avoid. But we must have caution with arrays and objects in order to not change the pointer reference, is recommended to clone the object/array once is passed as parameter in the functions if a change needs to be made on them, and then return the new object.

Referencial transparency

The sum of Pure Functions plus Immutable Data returns Referencial Transparency. The function are not going to modify any global variables, and only will work with their scope variables. Once the function returns a value, it will be assigned to a new variable. Example:

const number = 3;

const square = x => x ** 2;

const result = square(number)

console.log(result) // 9
Enter fullscreen mode Exit fullscreen mode

First-class functions

First-class functions are functions that are treated as variables and can be passed to another functions as arguments.

const numbers = [2, 5, 3, 8, 10];

const double = (x) => x * 2;

const doubleNumbers = numbers.map(double);

console.log(doubleNumbers) // [ 4, 10, 6, 16, 20 ]
Enter fullscreen mode Exit fullscreen mode

In the example above, the double function is considered as first-class function because is treated as variable, and also is being passed in the map function.

High order functions

High-order functions are functions that accept another functions as arguments or returns a function as an output.

Array procedures like map, reduce or filter are considered as high-order functions. Also, methods can be created that match this definition.

Recursion instead of loops

In functional programming is needed to avoid using loops, because they are required to change the state outside their scope for the purpose to finish the cycles.

// Loop

let loopSum = 0
const loopLimit = 15

for (let i = 0; i <= loopLimit; i++) {
   loopSum += i;
}

console.log(loopSum) // 120


// Recursion

const recLimit = 15

const sumNum = (val, lim) => {
  if(val <= lim) {
    return val + sumNum(val + 1, lim)
  }

  return 0
}

console.log(sumNum(0, recLimit)) // 120
Enter fullscreen mode Exit fullscreen mode

In this previous script, we did both loop and recursion example. We can notice how loop change the global variable loopSum in every cycle. Instead the recursive way not changed any state that didn't belong to its scope.

Wrapping up

I hope you enjoyed this information about functional programming in JavaScript with me! For some it may be a new programming paradigm, but I hope you will try to use it. I think your applications will be easier to read and debug. If you have any suggestions, comments or questions, let me know in the comments. Thanks!

Top comments (0)