Basics of Closures & Currying in JavaScript

Basics of Closures & Currying in JavaScript

Closures and Currying are also important concepts to understand when it comes to functional programming where they essentially serve a similar purpose to private methods in Object Oriented Programming.

Closures and Currying are also important concepts to understand when it comes to functional programming where they essentially serve a similar purpose to private methods in Object Oriented Programming.

Table of Contents

  • What are Closures?
  • Why use closures?
  • Currying
  • Conclusion 

What are Closures?

If you write code in JavaScript it's quite likely you have come across the term closure, which is a useful yet often confusing concept. But just what is a closure? 

If you write code in JavaScript it's quite likely you have come across the term closure, which is a useful yet often confusing concept. But just what is a closure?

A closure may be described as a combination of a function and the lexical environment in which it was declared.

But what exactly does this mean? The lexical environment consists of any local variables in the function's scope when the function is created. A closure enables one to refer to all local variables of a function in the state they were found. This is essentially achieved by defining a function inside another function, this function within a function is technically the closure. Each time the parent function is called, a new context of execution is created holding a fresh copy of all local variables. These local variables can be referred to in the global scope by either linking them to variables declared globally or returning the closure from the parent function.

A simple example will take on a format similar to this:

function closuredFunc (){
    function closure(){
    // some logic
    }
}

It is also possible to have a closure that returns several methods as shown below:


function closure(){
    function first() { console.log('I was declared first')}
    function second() { console.log('I was declared second')}
    function third() { console.log('I was declared third')}
    return [first, second, third]
}

To reference each of these methods, we'll assign our closure to a global variable which will then point to an array of exposed methods. Each method can then be assigned to unique variable names to bring them into the global scope as shown below. At this point, they can now be called.

let f = closure()

let one = f[0]
let two = f[1]
let three = f[2]

one() // logs I was declared first
two() // logs I was declared second
three() // logs I was declared third

Why use closures?

You may be wondering why would one go through the trouble of making closures. Well, closures have a number of uses and advantages.

Prior to the introduction of Classes in ES6, closures provided a means of creating class-like privacy similar to that used in Object Oriented Programming, allowing us to emulate private methods. This is known as the module pattern and it allows us to right easily maintainable code with reduced namespace pollution and more reusability.

Let's look at a case where this is done.

var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }
};

var counter1 = makeCounter();
var counter2 = makeCounter();

counter1.value(); // returns 0
counter1.increment(); // adds 1
counter1.increment(); // adds 1
counter1.value(); // returns 2
counter1.decrement(); //subtracts 1
counter1.value(); // returns 1
counter2.value(); // returns 0

In the above example, we have declared a function makeCounter which is a public function that has access to some private variables within it such as privateCounter and the functions that manipulate it. This mimics the behaviour of creating makeCounter as a class with it's own built in fuctionality and variables. This can be seen when we create two different counters, counter1 and counter2 . Each counter is independent to the other and references a different version of variables.

Closures also allow us to use functions to create other functions that add a specific value to their argument. In this case, the parent function allowing this behaviour is known as a function factory as it essentially creates other functions.

Using function factories, we are able to achieve a behaviour known as Currying .which we'll cover in the next section.

Currying

Currying is the pattern of functions that immediately evaluate and return other functions. This is made possible by the fact that Javascript functions are expressions that can return other functions.

Curried functions are constructed by chaining closures by defining and immediately returning their inner functions simultaneously.

Here's an example of currying:

let greeting = function (a) {
    return function (b) {
        return a + ' ' + b
    }
}

let hello = greeting('Hello')
let morning = greeting('Good morning')

hello('Austin') // returns Hello Austin
hello('Roy') // returns Hello Roy
morning('Austin') // returns Good morning Austin
morning('Roy') //returns Good Morning Roy

The two functions created from greeting ( hello and morning )each return functions that process the provided inputs to generate a greeting statement. They also take an argument which is the name of the person to be greeted.

In the above case, greeting is also used as a function factory with the two functions hello and morning generated from it.

The inner function may also be called invoked after the first call as follows:

greeting('Hello There')('General Kenobi') 
//returns Hello There General Kenobi

Currying is considered to be part of functional programming and as such curried functions may be easily written using the arrow function syntax in ES6 and newer versions of Javascript for cleaner, more elegant code.

let greeting = (a) => (b) => a + ' ' + b 

greeting('Hello There')('General Kenobi') 
//returns Hello There General Kenobi

Conclusion

While closures may not be as commonly used since Javascript incorporated classes in ES6, they still have their place when it comes to writing clean reusable code. Closures and Currying are also important concepts to understand when it comes to functional programming where they essentially serve a similar purpose to private methods in Object Oriented Programming.

javascript

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

The essential JavaScript concepts that you should understand

The essential JavaScript concepts that you should understand - For successful developing and to pass a work interview

Data Types In JavaScript

JavaScript data types are kept easy. While JavaScript data types are mostly similar to other programming languages; some of its data types can be unique. Here, we’ll outline the data types of JavaScript.

JavaScript Memory Management System

The main goal of this article is help to readers to understand that how memory management system performs in JavaScript. I will use a shorthand such as GC which means Garbage Collection. When the browsers use Javascript, they need any memory location to store objects, functions, and all other things. Let’s deep in dive that how things going to work in GC.

Create a Line Through Effect with JavaScript

In this post we are going to create an amazing line through effect, with help of CSS and lots of JavaScript. So, head over to your terminal and create a folder LineThroughEffect. Create three files -index.html, main.js and styles.css inside it.

Grokking Call(), Apply() and Bind() Methods in JavaScript

In this article, we will have a look at the call(), apply() and bind() methods of JavaScript. Basically these 3 methods are used to control the invocation of the function.