JavaScript always had functional programming principles built right into it. The major concept which supports it is treating functions as a first class object which means that the function can behave as an object, returned as a value from a function, passed as a parameter.

Advantages include code readability and clarity.

Functional programming supports declarative style of programming. There are three major principles for functional programming.

  • Pure functions
  • Avoid side effects
  • Avoid sharing state

Pure function :

 A function that given the same input always returns the same output. It has no global dependency, supports data immutability and better testability. E.g.

function add(a,b){
  return a+b;
}

The above add function accepts two number and returns their sum without changing any internal state.

Side effects:

A function that modifies or changes the internal state is said to have side effects. E.g

class Demo{

 constructor(){
  this.result = null
 }

 add(a,b){
  this.result = a+b;
  return this.result; 
  }
}

 

The above function modifies the internal state of class Demo named result inside the add function, hence this is considered as an impure function.

Shared State:

A function which shares state from other function, in short, multiple functions having the dependency on the same state. E.g.

  • Global Variables
  • Reference variables
  • Closures

 

Let's see few examples of writing functional programming using a custom map and filter function.

Problem 1: Given an array return a new array by multiplying each item by 2.

Traditional way or imperative way of programming:

<script>

let arr = [1,2,3,4,5,6,7,8,9];
let arrSize =  arr.length;
let newarr = [];
for(let i =0 ;i < arrSize; i++){
   newarr.push(arr[i] * 2)
}

console.log("new array", newarr)

</script>

 

In the above program, we are iterating over an array and multiplying each item with 2 and pushing it to the new array.

A functional or declarative way of programming:

<script>

var customMap = function(arr, fn) {
    if (arr != undefined) {
        var newarr = []
        var arrSize = arr.length;
        for (let i = 0; i < arrSize; i++) {
            newarr.push(fn(arr[i]))
        }
        return newarr;
    }
}

var result = customMap(arr, function(item) {
    return item * 2
})
console.log(result);

</script>

 

In the above program, a customMap function is defined which accepts an array and a function as an argument. All the major code is abstracted inside the customMap function.

#8  is very important, here we push the function as an argument by invoking it inside push method.

#14  passes a function expression which returns each item by multiplying it by 2.

 

Let's see another example of a custom filter function.

Problem 2: Given an array return a new array of only even numbers.

<script>
    var customFilter = function(arr, fn) {
        if (arr != undefined) {
            var newarr = []
            var arrSize = arr.length;
            for (let i = 0; i < arrSize; i++) {
                if (fn(arr[i])) {
                    newarr.push(arr[i]);
                }
            }
            return newarr;
        }
    }

    var result = customFilter(arr, function(item) {
        return item % 2 == 0;
    })
    console.log(result); // [2, 4, 6, 8]
</script>

 

The above program defines a customFilter function which accepts an array and a function as an argument.

#7 invokes the function expression passed as a parameter at #15 which returns a boolean value hence only even numbers are pushed to the new array.