JavaScript Closures Explained with Examples

JavaScript closures can be a tricky concept for beginners to understand, but they are an essential part of the language. In this tutorial, we will cover what closures are, how they work, and some common use cases.

In JavaScript, a closure is created when a function is defined inside another function, and the inner function has access to the outer function’s variables and parameters. In other words, a closure is a combination of a function and the environment in which it was declared.

How do closures work?

JavaScript uses lexical scoping to determine the scope of variables and functions. Lexical scoping means that the scope of a variable or function is determined by its position in the code.

When a function is defined inside another function, the inner function forms a closure over the outer function’s variables and parameters. This means that the inner function has access to these variables and parameters even after the outer function has completed execution.

Here’s an example to help illustrate this concept:

function outer() {
  const name = 'John';

  function inner() {
    console.log(`Hello ${name}!`);
  }

  return inner;
}

const greet = outer();
greet(); // Output: Hello John!

In this example, the inner function is defined inside the outer function and has access to the name variable. When the outer function is called, it returns the inner function, which is then assigned to the greet variable. When greet is called, it logs “Hello John!” to the console, even though the outer function has already completed execution.

Private variables and functions

Closures can be used to create private variables and functions in JavaScript. A private variable or function is one that is not accessible outside the scope of the closure.

function counter() {
  let count = 0;

  return function() {
    count++;
    console.log(count);
  }
}

const increment = counter();
increment(); // Output: 1
increment(); // Output: 2
increment(); // Output: 3

In this example, the counter function returns an inner function that increments a private count variable and logs its value to the console. The count variable is not accessible outside the closure, so it cannot be modified or read directly.

Callback functions

In JavaScript, a callback function is a function that is passed as an argument to another function and is executed by that function. The callback function can access variables in its outer scope, including variables defined in the function that calls it.

Callback functions are commonly used in asynchronous programming, where a function needs to wait for an operation to complete before executing further code. In this case, the callback function is called once the operation is complete, allowing the program to continue executing.

Closures can be used to create callback functions that have access to variables in their outer scope.

function getData(url, callback) {
  const xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
      const data = JSON.parse(xhr.responseText);
      callback(data);
    }
  };

  xhr.open('GET', url);
  xhr.send();
}

getData('https://example.com/data', function(data) {
  console.log(data);
});

The callback function has access to the data variable in its outer scope, which is the result of the getData function.