JavaScript the Fun Part


functional-programming-javascript

closure


In previous post (function as first class citizen) we talked about function as first class citizen, the most important part of FP. This post is about the second most important part which is closure.

In simple words it means a function that has access to its outer scope variables by reference via scope chain.

Garbage Collection

In none function languages that do not have this feature, this is what happens when we declare some variables inside a function and that function is executed.

In dynamic languages like JavaScript who does the deallocation part? Garbage Collector or GB. So after the last line of a function which is } was run then we do hot have access to these variables.

This process is not true for languages that support closure. In fact if we have an inner function that uses a variable outside of its scope (= from its parent functions) then GB does not do its job which is deallocation after popping off a function from the stack.

And what do we have at the end? An inner function that has access to outer scope variables by reference..

function add( a, b ){
    function sum(){
        return a + b;
    }
    const r = sum();
    return r;
}

const result = add( 2, 3 );
console.log( result ); // 5

In the code above the bounded context of add() function is close over sum() function; and thus sum() can find a and b variables via scope chain. Since it is by reference we can do a very interesting thing!

What is that?

Function as value

Remember that function in FP languages is a first class citizen and we can treat it a value. In JavaScript we can return an inner function. Things get interested, specially when that function can have access to outer variables by reference (= closure).

Here is the same code but using different style, returning sum function.

function add( a, b ){
    function sum(){
        return a + b;
    }
    // we do not invoke sum(), we return it!
    return sum;
}

const sum = add( 2, 3 ); // return sum
console.log( sum() );   // 5

The output is still 5 because our nested function has access to a and b variables.

;

function expression or anonymous function

We know that we can do this is JS.

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

Which is equivalent to this in ES6 with Lambda Expression or Arrow Function.

const add = ( a, b ) => a + b;

Base on this fact, we can refactor our first code to a more concise one.

function add( a, b ){
    // name is optional, we can remove it
    // return function() ...
    return function sum(){
        return a + b;
    }
}

const add2And3 = add( 2, 3 );   // returning a function expression
console.log( add2And3() );        // 5

And in ES6

const add = ( a, b ) => () => a + b;
const add2And3 = add( 2, 3 );
console.log( add2And3() );      // 5

This is what we can do by combining two features

  1. function as first class citizen
  2. closure
function add( a, b ){
    // returning a function expression
    return function(){
        return a + b;
    }
}

const sum = add( 2, 3 ); // return sum
console.log( sum() );   // 5

While this is very good and awesome but we can still go further by using another important concept which is currying and we explore it in next post.

So in next post we add currying to the mix and we will have

  1. function as first class citizen
  2. closure
  3. currying

Update: Sun Nov 03 2019 07:51:18 GMT+0330 (Iran Standard Time)