Introduction to Javascript closure

Introduction

JavaScript closure is one of the most important concepts if you want to go anywhere with JavaScript. It is as important as pointers in C/C++. Closures empower JavaScript developers to write better code. So, if you want to become a better JavaScript developer, learn closures.With great power comes great responsibility however. Therefore, if misused, they can create a nightmare. In order to learn functional programming in JavaScript, developers first need to have a solid understanding of how JavaScript closure works.

Readers should have a firm understanding of the following topics.

JavaScript closure is important. But what is it?

A closure is an inner function that has access to the outer function’s scope. Basically the closure has access to variables in the following scope.

  1. The global scope
  2. Outer function’s scope
  3. Its own scope

If we get all technical and have a closure of a closure, it will have access to four scopes and so on. Therefore, knowledge and understanding of scope becomes paramount. JavaScript closure is considered to be a fairly advanced topic. Before proceeding, make sure you have a strong knowledge of functions and variable scopes before proceeding.

Simple JavaScript Closure Example

Therefore, because of their power, closures are used extensively in every major frameworks. Since it is such an important topic, numerous examples of closures will be covered in this post.

function regularFunction(age) {
    var name = "Jay";
    function closure() {
        var gargbageText = " Full stop.";
        return name + ". Age: " + age + gargbageText;
    }
    return closure;
}

var closures = regularFunction(15);   // returns a function that returns name;
console.log(closures());

As shown above, regularFunction accepts an age variable. Remember that JavaScript does not have block scopes. But rather, it has function scope.

Therefore, function closure() should not have access to the variables age and name right? WRONG!

Remember when I said that inner functions have access to the outer functions variable scope? That is the key! closure() has access to name and age.

Even after regularFunction() executes on line 10, the inner function still has reference  to the variables in the outer function. What does this mean? It means that we don’t have a copy of the values, but their references. Therefore, we are able to manipulate the actual value stored in the variables name and age.

Intermediate Examples

Now that we have basic knowledge of closures, lets look at some more examples. The following section displays practical use cases.

Encapsulation

function house(price) {
    // We don't want users to change the price.
    // But we want them to be able to see and retrieve it.
    return {
        getPrice: function getPrice() {
            return price;
        }
    }
}

var myHome = house(250000);
console.log(myHome.getPrice());

As shown above, the

price

variable is encapsulated. Therefore, the consumer of the API has read-only access to the price. As shown above,

house()

returns an object with a function value assigned to the key

getPrice

. Therefore, users are only given access to read the price.

Partial Application

Partial application is a very common use case of closures. Another term used for it is currying. Going in-depth into this  topic will take up a whole post. Therefore, I will post just a simple example below.

function add(num) {
    return function doSum(newNumber) {
        return num + newNumber;
    }
}

var add5 = add(5);
console.log(add5(6));       // 11

The code posted above is probably the most common example for explaining currying.

add()

accepts a number and returns another function

doSum

.


It returns the sum of the variable passed into the outer function and the result (

num

and

newNumber

respectively). As a result, we can create a function that performs a single action. In our example, it is the act of adding 5 to whatever is passed in. As a result, JavaScript developers are able to write modular, easy to debug code.

In my opinion, functions should generally perform one action. From personal experience, in the front-end, bugs in JavaScript are often created, because a single function is doing something it is not supposed to. In another words, it is doing too many things. This creates nasty side-effects, resulting in code that is difficult to debug.

Putting Everything Together

In this section, we will apply everything that we learnt. But, before going in, the source will be fairly challenging. Therefore, don’t be dismayed if you don’t understand it all in one go. Take time to read and review the information. After reading, if certain parts require more explanation, or if it was poorly written, please let me know. Constructive feedback is more than welcome.

In the example, I will be utilizing the module pattern. In the previous section, we talked about encapsulation. It provides an excellent way to hide implementation details. As a result, consumers only need to know the public API.

Closures Delight

// Generator function made from applying concepts in lecture
var randomNumberProcessor = function randomNumberProcessor(algorithm) {
    return function getRandomNumber(min, max) {
        return algorithm(min, max);
    };
};

// Compose randomNumberProcessor and generateRandomInt. Generate a random number (no decimal place).
var generateRandomInt = randomNumberProcessor(function (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
});

var generateRandomDouble = randomNumberProcessor(function (min, max) {
    return  Math.random() * (max - min) + min;
});

In the code above,

randomNumberProcessor()

accepts a function called

algorithm

and returns a function

getRandomNumber

. Since

randomNumberProcessor

returns a function, we can use it to generate functions that address their problem. In the example above

generateRandomInt

is used to generate whole numbers.

generateRandomDouble

generates numbers, including those with decimal points.  Because of closures we are able to generate random whole numbers and decimals on demand.

As shown in the example above, closures provide developers with the option to write more generic cod. This could possibly reduce the amount of boilerplate code written. Developers can use these abstractions to create implementations that addresses their current problem.

Source Code

The source code can be found on github. Once again, thank you so much for taking time to read this. Please let me know what you thought of it. As always, I welcome feedback.

About the Author Jay

I am a programmer currently living in Seoul, South Korea. I created this blog as an outlet to express what I know / have been learning in text form for retaining knowledge and also to hopefully help the wider community. I am passionate about data structures and algorithms. The back-end and databases is where my heart is at.

follow me on: