Closures in JavaScript
Tags: javascript, webdev, beginners, codenewbie
Published: 2023-10-18 06:25:49

closures are a fundamental and powerful concept in JavaScript and many other programming languages. They allow functions to "remember" and access variables from their containing (enclosing) scope even after that scope has exited. To understand closures in detail, let's break down the key components and concepts associated with them.

1. **Nested Functions:** Closures arise from the use of nested functions, which means defining one function within another. The inner function is said to be a closure because it "closes over" the variables from the outer function's scope. [[Nested Functions]]
    
2. **Lexical Scoping:** JavaScript uses lexical Scoping, which means that the scope of a variable is determined by its location within the source code (the lexicon). In other words, it depends on where a variable is declared, not where it's called or used.
    
3. **Accessing Variables:** Closures can access variables from their containing (outer) function, even after the outer function has completed execution and its scope has technically exited.
    
4. **Function as First-Class Citizens:** In JavaScript, functions are first-class citizens, which means they can be assigned to variables, passed as arguments to other functions, and returned from functions. This flexibility is crucial for working with closures.

```JS
function outer() {
  let outerVar = 10;

  function inner() {
    console.log(outerVar);
  }

  return inner;
}

const closureFunc = outer();
closureFunc(); // This still logs "10" even though outer() has completed.

```
In this example, `inner` is a closure because it "closes over" the `outerVar` variable from the `outer` function. Even after `outer` has completed execution, when we call `closureFunc()`, it can still access and log the value of `outerVar`.

**Use Cases for Closures:** Closures have several practical applications, such as:

- **Data encapsulation and information hiding**: You can use closures to create private variables and methods.
- **Function factories:** You can create functions that generate other functions with specific behavior.
- **Callbacks and event handling:** Closures are commonly used to manage callbacks and event handlers.
- **Memoization**: Closures can be used to cache results of expensive function calls.
- **Module patterns:** Closures enable the creation of modules with private and public parts.

### Closure Related Issues and Solution through IIFE

consider this code : 

```js
for (var i = 1; i <= 4; i++) {
    setTimeout(function () {
        console.log(i);
    }, i * 10000);
}

//console output
//5(4 times)
```

In this code, we have a loop that runs from `i` values 0 to 4. Inside the loop, there's a `setTimeout` function that logs the value of `i` after a 1-second delay. You might expect this code to log 0, 1, 2, 3, and 4, each after a 1-second delay. However, it doesn't work as expected. It logs the value 5 five times after 1 second because the loop variable `i` is shared among all the timeouts.

Here's why this happens:

1. The loop runs and increments `i` from 0 to 4.
2. The `setTimeout` callbacks are scheduled to run after a 1-second delay, *but they don't execute immediately.*
3. By the time the callbacks run, the loop has already finished, and `i` has a final value of 5.

So, all the `setTimeout` callbacks capture the same `i`, which is 5 when they execute. This behavior is because closures in JavaScript capture variables by reference, not by value. Therefore, all the callbacks see the same `i`, which is 5.

To solve this issue, developers often use the approach shown in your initial code snippet:
```js
for (var i = 1; i <= 4; i++) {
  (function (j) {
    setTimeout(function () {
      console.log(j);
    }, j * 1000);
  })(i);
}

```
In this version, an [[immediately invoked function expression (IIFE)]] is used to create a new scope for each iteration of the loop. The `j` variable inside the IIFE captures the current value of `i` for that specific iteration, preventing the closure over the loop variable problem. As a result, each `setTimeout` callback logs the correct value of `j`.

### The closure related issues due to difference between using let and var

**`var`:** Variables declared with `var` in a loop often lead to unintended closure-related issues, as we saw in your initial code snippet. This is because they capture the variable by reference and not by value, causing all closures to share the same reference.
        
**`let`:** Variables declared with `let` in a loop create a new variable with each iteration, effectively capturing the value of the variable at that iteration. This behavior is why `let` is often preferred in situations where you want to avoid closure-related problems.

```js
// Using var
for (var i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  }, 1000);
}


```
With `var`, there's a single `i` variable with function scope. All five `setTimeout` callbacks capture the same `i` by reference, so when they execute, they all see the final value of `i`, which is 5.

```js
// Using let
for (let i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  }, 1000);
}

```
With `let`, there are five separate `i` variables with block scope, one for each iteration. Each `setTimeout` callback captures its own `i`, and when they execute, they log the value of `i` from their respective block scopes, resulting in the expected output of 0, 1, 2, 3, and 4


`let` provides block-scoping, which is well-suited for situations like loop counters, where you want to avoid closure-related issues and ensure that each iteration has its own isolated variable. `var`, on the other hand, is function-scoped and can lead to unintended behavior in certain situations.
in order to better understand this read [[Difference between let and var]]


### Emulating private methods with closures

JavaScript, prior to classes, didn't have a native way of declaring private methods, but it was possible to emulate private methods using closures. Private methods aren't just useful for restricting access to code. They also provide a powerful way of managing your global namespace.
```js
const counter = (function () {
  let privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }

  return {
    increment() {
      changeBy(1);
    },

    decrement() {
      changeBy(-1);
    },

    value() {
      return privateCounter;
    },
  };
})();

console.log(counter.value()); // 0.

counter.increment();
counter.increment();
console.log(counter.value()); // 2.

counter.decrement();
console.log(counter.value()); // 1.

```
each closure had its own lexical environment. Here though, there is a single lexical environment that is shared by the three functions: `counter.increment`, `counter.decrement`, and `counter.value`.

The shared lexical environment is created in the body of an anonymous function, _which is executed as soon as it has been defined_(also known as [[immediately invoked function expression (IIFE)]])
The lexical environment contains two private items: a variable called `privateCounter`, and a function called `changeBy`. You can't access either of these private members from outside the anonymous function. Instead, you can access them using the three public functions that are returned from the anonymous wrapper.

Those three public functions form closures that share the same lexical environment. Thanks to JavaScript's lexical scoping, they each have access to the `privateCounter` variable and the `changeBy` function.

```js

const makeCounter = function () {
  let privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment() {
      changeBy(1);
    },

    decrement() {
      changeBy(-1);
    },

    value() {
      return privateCounter;
    },
  };
};

const counter1 = makeCounter();
const counter2 = makeCounter();

console.log(counter1.value()); // 0.

counter1.increment();
counter1.increment();
console.log(counter1.value()); // 2.

counter1.decrement();
console.log(counter1.value()); // 1.
console.log(counter2.value()); // 0.

```

Notice how the two counters maintain their independence from one another. Each closure references a different version of the `privateCounter` variable through its own closure. Each time one of the counters is called, its lexical environment changes by changing the value of this variable. Changes to the variable value in one closure don't affect the value in the other closure