// Tutorial //

Understanding Closures in JavaScript

Published on August 26, 2021
Default avatar
By Vijay Prasanna
Developer and author at DigitalOcean.
Understanding Closures in JavaScript

Introduction

In this article, you will cover the basics of what a closure is and why JavaScript benefits from closures.

Prerequisites

If you would like to follow along with this article, you will need:

  • Familiarity with JavaScript variables, functions, scope, and callbacks.

Defining a Closure

A closure can be defined as a persistent scope that is held onto by a variable. Languages like JavaScript and Ruby support closures, which allows variables to have references to their parent scope even after their programming block has been executed and, as long as these variables have a reference somewhere, the closure exists.

Consider the following closure example:

function outerFunction() {
 let delayed = veryLongOperation();

 let innerFunction = function() { someCallback(delayed); }
}

The innerFunction is a function that is able to access its parent scope elements - like the delayed object.

Using Closures

Now that we’ve seen what closures are, why are they useful?

JavaScript can be asynchronous when it comes to execution. When an operation is completed, a callback has to be employed. This callback now has to run with the same execution context as its caller/parent. This means that whatever variables or functions were available to the parent must now be made available to the callback as well. If these callbacks did not have closures, then we’d have to manually bind the needed scope members.

Closures make our lives a lot easier by handling this for us in the background. If there is a function inside a function, the inner function has access to its scope members throughout its lifetime.

Consider the following class definition example:

let classExample = function () {
  let randomNumber = Math.floor(Math.random() * 10);

  return function() {
    console.log(randomNumber);
  }
}

The scope chain of the inner function is extended to include the members of the classExample function.

Another instance where closures come into play is during currying. Currying is the process of returning multiple functions to reduce arity. It’s employed in functional programming paradigm to reduce state changes.

Closures can be used along with currying to introduce private members for JavaScript classes.

function curryingExample() {
  let message = "Hello.";

  return {
    getMessage: function() { console.log('private message', message); }
  };
}

Create a new curryExample() instance:

let curry = new curryingExample();

Attempt to access message:

console.log('undefined message', curry.message);

When console.log(curry.message); executes the value will be undefined.

Attempt to use getMessage():

curry.getMessage();

When curry.getMessage(); executes, the value will be "Hello.".

Conclusion

Closures are a very subtle yet powerful feature of JavaScript and understanding them is a very important step on the path to becoming a serious JavaScript developer.

This is explained in more detail in Kyle Simpson’s excellent write-up on Closures.


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
Leave a comment

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!