JavaScript Closures Explained with Examples
Published: 2024-01-08 17:10:26

A **closure** is an inner function referencing one or more items in its [lexical scope](https://codesweetly.com/javascript-lexical-scope) (definition area).

**Note:** An inner function is a function defined inside a [block](https://codesweetly.com/code-block), [module](https://codesweetly.com/javascript-modules-tutorial), or another function.

In other words, a closure is a function that retains access to its lexical scope's features even after its execution closes.

For instance, consider the following code:

```js
function createProfile() {
  const myName = "Oluwatobi";
  function showName() {
    return myName;
  }
  return showName();
}
createProfile();
```

[**Try Editing It**](https://codesweetly.com/try-it-sdk/javascript/function/closures/js-z2eyrx)

`showName()` is the closure in the example above because:

- It is an inner function.
- It retains a reference to its lexical scope's variable.

**Note:**

- The `createProfile()` function's body is `showName()`'s lexical scope.
- The `showName()` function retained a reference to its lexical scope's [state](https://codesweetly.com/state-in-programming) (variable's value) by calling `myName`.
- The reason `showName()` is a closure is not because it was returned nor invoked within `createProfile()`. Instead, it is a closure because it is an inner function that retains a reference to its lexical scope's feature (that is, `myName`).
- All closures have three scopes:
  - **Local scope:** The space within the closure.
  - **Parent scope:** The space of the closure's block, module, or parent function. In other words, the parent scope is the outer/enclosing environment.
  - **Global scope:** The space containing all the scopes/code.

So, now that we know what a closure is, we can discuss how browsers will process `createProfile()`'s invocation.

## How Do Browsers Process a Closure's Lexical Scope's Invocation?

Below is a walk-through of how JavaScript will process the `createProfile()` function's invocation.

### 1. Allocate memory

```js
{ // This is the createProfile() function's opening block
```

The first thing JavaScript does when browsers invoke `createProfile()` is to allocate the memory it needs to process the function's invocation.

### 2. Parse the variable's declaration

```js
const myName;
```

JavaScript's second task is to analyze `myName`'s declaration, following the [hoisting](https://codesweetly.com/javascript-hoisting) principles.

### 3. Parse the function's declaration

```js
function showName() {}
```

The computer's third step is to analyze `showName()`'s declaration, following the hoisting principles.

### 4. Initialize the variable

```js
myName = "Oluwatobi";
```

The computer initializes `myName` with the `"Oluwatobi"` string value, following the hoisting principles.

### 5. Return the invoked function's output

```js
return showName();
```

The fifth thing JavaScript does is to return `showName()`'s output to the `createProfile()` function.

### 6. Return the variable's content

```js
return myName;
```

JavaScript returns the variable's value to the `showName()` function's invocation.

### 7. Empty the allocated memory

```js
} // This is the createProfile() function's closing block
```

The computer ends the `createProfile()` function's execution and empties the allocated memory. Therefore, all the values JavaScript stored in `createProfile()`'s allocated memory will vanish forever!

So, what makes closures unique? Let's discuss this now.

## What Makes Closures Unique?

No external scope can access a function's data by default, but a closure's scope can.

For instance, the snippet below returned an error because the global scope cannot access the `createProfile()` function's space.

```js
// Define the createProfile function:
function createProfile() {
  const myName = "Oluwatobi";
}

// Call myName variable:
myName;

// The call above will return:
// Uncaught ReferenceError: myName is not defined
```

[**Try Editing It**](https://codesweetly.com/try-it-sdk/javascript/function/closures/js-ik7rqv)

You can, however, use closures to access `createProfile()`'s scope from another environment.

**Here's an example:**

```js
// Define the createProfile function:
function createProfile() {
  const myName = "Oluwatobi";
  function showName() {
    return myName;
  }
  return showName;
}

// Invoke the createProfile and store its output in a variable:
const firstName = createProfile();

// Check the content inside the firstName variable:
firstName;

// The call above will return:
// function showName() {
//   return myName;
// }

// Invoke the function stored in the firstName variable:
firstName();

// The invocation above will return:
// "Oluwatobi"
```

[**Try Editing It**](https://codesweetly.com/try-it-sdk/javascript/function/closures/js-2vkxrg)

**Note:** `createProfile()` returned its inner function (the closure)—not the result of an invocation.

**Question:** Since the `firstName` variable contains only a function (`showName()`), how did the `showName` external function get access to `createProfile()`'s variable?

**Answer:** The reason the `firstName` variable's function gained access to `createProfile()`'s variable is because:

1. The `firstName` variable's function is a closure.
2. Closures retain reference to their lexical scope's data—even after JavaScript has closed their definition space's execution.

Let's discuss the reasons above in more detail.

## How Do Closures Retain Access to Their Lexical Scope's Features?

Closures retain access to their lexical scope's features by storing referenced items in-memory.

For instance, reconsider our previous example:

```js
// Define the createProfile function:
function createProfile() {
  const myName = "Oluwatobi";
  function showName() {
    return myName;
  }
  return showName;
}

// Invoke createProfile and store its output in a variable:
const firstName = createProfile();

// Check the content inside the firstName variable:
firstName;

// The call above will return:
// function showName() {
//   return myName;
// }

// Invoke the function stored in the firstName variable:
firstName();

// The invocation above will return:
// "Oluwatobi"
```

[**Try Editing It**](https://codesweetly.com/try-it-sdk/javascript/function/closures/js-2vkxrg)

Here's is how the computer will analyze the snippet above:

### 1. Allocate memory

```js
{ // This is the createProfile() function's opening block
```

The first thing JavaScript does when browsers invoke `createProfile()` is to allocate the memory it needs to process the function's invocation.

### 2. Parse the variable's declaration

```js
const myName;
```

JavaScript's second task is to analyze `myName`'s declaration, following the [hoisting](https://codesweetly.com/javascript-hoisting) principles.

### 3. Parse the function's declaration

```js
function showName() {}
```

The computer's third step is to analyze `showName()`'s declaration, following the hoisting principles.

### 4. Initialize the variable

```js
myName = "Oluwatobi";
```

The computer initializes `myName` with the `"Oluwatobi"` string value, following the hoisting principles.

### 5. Return the function

```js
return showName;
```

The fifth thing JavaScript does is to return the `showName` function to `createProfile()`.

**Note the following:**

- The computer will store the returned `showName` function in the `firstName` variable since that's where the `createProfile()` invocator lives.
- JavaScript will also store `myName`'s value in the `firstName` variable's memory because `showName` referenced it.
- The `firstName` variable's copy of `showName` and `myName` are _new_ code instances the computer created during `createProfile()`'s execution.
- Browsers will not run the `"return myName"` code at this stage because we did not invoke `showName`.

### 6. Empty the allocated memory

```js
} // This is the createProfile() function's closing block
```

The computer ends the `createProfile()` function's invocation and empties the allocated memory. Therefore, all the values JavaScript stored in `createProfile()`'s allocated memory will vanish forever!

### TLDR

The main gist of the walk-through above is this:

- The `const firstName = createProfile()` statement made the computer do the following:

  - Invoke `createProfile()`.
  - Store the invocation's returned function in the `firstName` variable.
  - Store `myName`'s current state (which `showName()` referenced) in the `firstName` variable's memory.

Therefore, here is what will happen whenever you invoke `firstName`'s function:

### 1. Allocate memory

```js
{ // This is the showName() function's opening block
```

The first thing JavaScript does when browsers invoke `showName()` is to allocate the memory it needs to process the function's invocation.

### 2. Return the variable's content

```js
return myName;
```

The computer analyzes the `return` statement by doing the following:

1. It checks if there's a `myName` variable definition locally within the `showName()` function's local scope. But there's none, so the computer moves up to check the next scope—the `firstName` variable's environment.
2. JavaScript searches for `myName` in the `firstName` variable's memory. Fortunately, it found `myName` there! Therefore, the computer gets `myName`'s content (`"Oluwatobi"`) and returns it.

**Note:** The computer found `myName` in `firstName`'s memory because JavaScript also stored all the data `showName()` referenced while storing `showName` inside `firstName`.

### 3. Empty the allocated memory

```js
} // This is the showName() function's closing block
```

The computer ends `showName()`'s execution and empties the allocated memory. Therefore, all the values JavaScript stored in `showName()`'s allocated memory will vanish forever!

**Note:**

- The `myName` variable will persist even after the computer closes `showName()`'s execution. This is because JavaScript stored `myName` in `firstName`'s memory—not inside `showName()`'s memory.
- The computer will empty `firstName`'s memory when it closes its scope's execution.

So, now that we know how closures retain access to their lexical scope's features, we can discuss a few more examples.

## Example 1: Generate Prepublication Years

```js
// Define the generateYear function:
function generateYear() {
  let publicationYear = 2023;
  function decreasePublicationYear() {
    return --publicationYear; // The -- operator subtracts one from the publicationYear variable.
  }
  return decreasePublicationYear;
}

// Invoke generateYear and store its output in a variable:
const prePublicationYear1 = generateYear();

// Invoke another instance of generateYear and store its output in a variable:
const prePublicationYear2 = generateYear();

// Invoke the function stored in the prePublicationYear1 variable:
prePublicationYear1();

// The invocation above will return: 2022

// Invoke the prePublicationYear1's function again:
prePublicationYear1();

// The invocation above will return: 2021

// Invoke the prePublicationYear1's function one more time:
prePublicationYear1();

// The invocation above will return: 2020

// Invoke the function stored inside the prePublicationYear2 variable:
prePublicationYear2();

// The invocation above will return: 2022
```

[**Try Editing It**](https://codesweetly.com/try-it-sdk/javascript/function/closures/js-gthfsz)

The snippet above consistently returns a value that is one (1) less than the previous year because:

1. JavaScript also stored all the data `decreasePublicationYear()` referenced while storing `decreasePublicationYear` inside `prePublicationYear`.
2. `prePublicationYear`'s copy of the `publicationYear` variable remains accessible even after the computer closes `decreasePublicationYear()`'s execution.

**Note:**

- `prePublicationYear1` and `prePublicationYear2` have different versions of `generateYear()`'s output because the computer creates new instances during each `generateYear()`'s execution.
- The subtraction happens on `prePublicationYear`'s copy of the `publicationYear` variable—not on the one inside the `generateYear()` function.
- The `--publicationYear` code uses the [decrement operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Decrement) to subtract one from the `publicationYear` variable and return the value after the decrement.

## Example 2: Generate the Multiple of a Constant

```js
// Define the generateMultipleOfX function:
function generateMultipleOfX(x) {
  return function multiplyXByY(y) {
    return x * y;
  };
}

// Invoke generateMultipleOfX and store its output in a variable:
const multipleOfX = generateMultipleOfX(3);

// Invoke the multipleOfX variable's function:
multipleOfX(2);

// The invocation above will return: 6

// Invoke the multipleOfX variable's function again:
multipleOfX(10);

// The invocation above will return: 30

// Invoke the multipleOfX variable's function one more time:
multipleOfX(1);

// The invocation above will return: 3
```

[**Try Editing It**](https://codesweetly.com/try-it-sdk/javascript/function/closures/js-84fhua)

The snippet above consistently multiplies `multipleOfX`'s argument by `3` because:

1. JavaScript also stored all the data `multiplyXByY()` referenced while storing `multiplyXByY()` inside the `multipleOfX` variable. (In the instance above, `multiplyXByY` referenced `3` (parameter `x`'s value)).
2. `multipleOfX`'s copy of the value `3` remains accessible even after the computer closes `multiplyXByY()`'s execution.

**Note:**

- The multiplication happened on `multipleOfX`'s copy of `generateMultipleOfX`'s argument.
- Your closure can be an [anonymous function](https://codesweetly.com/web-tech-terms-a#anonymous-function). We named the ones above for ease of referencing.

## Example 3: Create a Publication Year Calculator

```js
// Define the publicationYearCalculator function:
const publicationYearCalculator = (function () {
  let publicationYear = 2023;
  function updatePublicationYear(value) {
    publicationYear += value;
  }
  return {
    addOne: function () {
      updatePublicationYear(1);
    },
    subtractOne: function () {
      updatePublicationYear(-1);
    },
    defaultYear: function () {
      return publicationYear;
    },
  };
})();

// Check the publicationYearCalculator variable's content:
publicationYearCalculator;

// The invocation above will return:
// {addOne: ƒ, subtractOne: ƒ, defaultYear: ƒ}

// Invoke publicationYearCalculator's defaultYear() method:
publicationYearCalculator.defaultYear();

// The invocation above will return: 2023

// Invoke publicationYearCalculator's addOne() method:
publicationYearCalculator.addOne();

// The invocation above will return "undefined" because
// we programmed addOne() to invoke updatePublicationYear()
// only rather than return the result of the invocation.
// So, addOne() will increment publicationYear by one but
// will not return any value.

// Invoke publicationYearCalculator's defaultYear() method:
publicationYearCalculator.defaultYear();

// The invocation above will return: 2024

// Invoke publicationYearCalculator's subtractOne() method thrice:
publicationYearCalculator.subtractOne();
publicationYearCalculator.subtractOne();
publicationYearCalculator.subtractOne();

// Similar to the addOne() invocation, the invocations above
// will return "undefined" because we programmed subtractOne()
// to invoke updatePublicationYear() only rather than return
// the invocation's result.

// Invoke publicationYearCalculator's defaultYear() method:
publicationYearCalculator.defaultYear();

// The invocation above will return: 2021
```

[**Try Editing It**](https://codesweetly.com/try-it-sdk/javascript/function/closures/js-24htdf)

The `defaultYear()` method remembers the `publicationYear`'s updated state because:

1. JavaScript also stored all the data `updatePublicationYear()` referenced while storing `updatePublicationYear`'s invocator inside the `publicationYearCalculator` variable. (In the instance above, `updatePublicationYear` referenced `publicationYear`).
2. `publicationYearCalculator`'s copy of `publicationYear` remains accessible even after the computer closes `updatePublicationYear()`'s execution.
3. The calculation happened on `publicationYearCalculator`'s copy of `publicationYear`—not on the one inside the anonymous function.

**Note the following:**

- The `publicationYearCalculator` variable's function is an [Immediately Invoked Function Expression](https://codesweetly.com/javascript-function-object#what-is-a-javascript-immediately-invoked-function-expression) (IIFE).
- Developers use the term "[module pattern](https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch09s02.html)" to reference the neat organization of private and public features inside an [object](https://codesweetly.com/javascript-non-primitive-data-type) (as we've done in the `publicationYearCalculator`'s IIFE above).
- `publicationYearCalculator`'s IIFE contains two private and three public items.
  - `publicationYear` and `updatePublicationYear()` are the private features.
  - `addOne()`, `substractOne()`, and `defaultYear()` are the public items because they are part of the returned object.
- Although private items are inaccessible outside their lexical scope, you can access them through the public closures—because they have access to in-memory copies of their referenced features even after JavaScript has closed the IIFE's execution.
- `updatePublicationYear()`, `addOne()`, `substractOne()`, and `defaultYear()` are all closures because they are inner functions that reference some of their lexical scope's features.

**Tip:** Exposing only the code you wish to make globally available is recommended. Private code restricts unwarranted access and accidental conflict with other interfaces/namespaces.

## Overview

This article discussed what JavaScript closure is. We also used examples to see how it works.