Understanding Closures in JavaScript with Simple Practical Examples
Tags: webdev, javascript, programming, beginners
Published: 2023-11-13 20:56:19

Closures are a fundamental yet powerful feature of JavaScript. They are often one of the most misunderstood concepts, specially among beginners. If you are looking to deepen your understanding of closures and learn how to use them in real world situations this article is for you.

**What Are Closures?**
In JavaScript a closure is a unique function that remembers the environment in which it was created. What it means is that it can access variables from its outer scope even after the outer function has finished the execution.

Here is a simple example to illustrate the concept of closures:

```javascript
function greet() {
  const name = 'Alex';
  function displayName() {
    alert('Hello, ' + name);
  }
  return displayName;
}

const myGreet = greet();
myGreet(); // Alerts "Hello, Alex"
```
In the code shown above `displayName` is a closure that encloses both the function itself and the environment in which it was created which includes the variable `name`.

**Why Use Closures?**
Closures are useful for many reasons:
- Closures allow you to emulate private variables which provides security and prevents the global namespace from being cluttered.
- Closures enable powerful functional programming techniques.
- Closures maintain state in an asynchronous javascript world.

**Here are some Practical Use Cases:**
1. **Data Encapsulation and Privacy:**
   ```javascript
   function createCounter() {
     let count = 0;
     return {
       increment() { count += 1; },
       get value() { return count; }
     };
   }

   const counter = createCounter();
   counter.increment();
   console.log(counter.value); // 1
   ```
   The `count` variable in above code is private. It is not accessible outside the scope of `createCounter` other than through the closure's methods.

2. **Event Handlers:**
   ```javascript
   function setupButton(buttonId) {
     const button = document.getElementById(buttonId);
     button.onclick = function() {
       alert('Button ' + buttonId + ' clicked');
     };
   }
   setupButton('myButton');
   ```
   Each button click handler created by `setupButton` in above code is a closure with access to its very own `buttonId` variable.

3. **Partial Applications or Currying:**
   ```javascript
   function multiply(a, b) {
     return a * b;
   }

   function createMultiplier(multiplier) {
     return function(x) {
       return multiply(x, multiplier);
     };
   }

   const double = createMultiplier(2);
   console.log(double(3)); // 6
   ```
   `createMultiplier` returns a closure that multiplies its argument by a fixed multiplier.

**Understanding the Nuances:**
Closures come with their own set of potential pitfalls such as the loop problem:

```javascript
for (var myi = 1; myi <= 5; myi++) {
  setTimeout(function() {
    console.log('myi: ' + myi);
  }, myi * 2000);
}
// Outputs "myi: 6" five times
```

You might expect the above code to log the numbers 1 to 5 after every two seconds gap. However it will actually print the number 6 five times two seconds apart instead. This happens because the setTimeout functions are executed after the loop has completed execution at which point the variable ‘myi’ has a value of 6.


To fix this using closures you can create a new scope by adding an Immediately Invoked Function Expression(IIFE) like below

```javascript
for (var myi = 1; myi <= 5; myi++) {
  (function(myj) {
    setTimeout(function() {
      console.log('myj: ' + myj);
    }, myj * 1000);
  })(myi);
}
```
We will not go deep into the above solution as we have a better solution for this problem in the next section. For now the quick explanation is -

myj is a parameter of the IIFE and myi is passed to it. As function parameters are local to the function this myj variable is different for each iteration which implies that setTimeout callback refers to the correct myj value when it’s called.

The modern day solution to this particular issue is to simply use let instead of var. As we already know that let is block-scoped and creates a new binding for each iteration

```
for (let myi = 1; myi <= 5; myi++) {
  setTimeout(function() {
    console.log(myi);
  }, myi * 1000);
}
```

With the help of let each loop iteration now creates a new myi variable scoped to that iteration. That means the setTimeout callback will work with the myi that is available at the time of the iteration and gives you the expected output.


Closures should not be seen as just a theoretical concept they are a practical tool that can solve real-world problems in JavaScript world. By understanding and applying closures correctly, you can write more efficient and extremely secure code. As you dive into open-source projects like OpenSign, you'll encounter closures frequently. Understanding them will help you contribute more effectively. Visit [OpenSign](https://github.com/opensignlabs/opensign) on GitHub to start your open source journey.

Now that you have a better grasp of closures, try implementing them in your next project or while contributing to an open-source initiative. Share your experiences or any questions in the comments below!

{% cta https://github.com/opensignlabs/opensign %} ⭐ OpenSign on GitHub{% endcta %}