DEV Community

Hussaini Ahmed
Hussaini Ahmed

Posted on

JavaScript Closures: Understanding Private Variables, Callbacks, and Memoization for Efficient Code

javascript closure

JavaScript is a powerful programming language that is used to create interactive websites and web applications. One of the most important concepts in JavaScript is closures. Closures can be a little tricky to understand at first, but once you get the hang of them, they can make your code much more powerful and flexible. In this article, we will explain what closures are, how they work, and how to use them in your code.


What are Closures?

A closure is a function that has access to its parent function's variables, even after the parent function has returned. In other words, a closure is created when a function is defined inside another function, and the inner function has access to the outer function's variables. This means that the inner function "closes over" the variables of the outer function, hence the name closure.


How do Closures Work?

To understand how closures work, let's look at an example. Consider the following code:

function outer() {
 var name = "Hussaini";
 function inner() {
 console.log(name);
 }
 return inner;
}
var closure = outer();
closure();
Enter fullscreen mode Exit fullscreen mode

In this code, we define a function called outer that contains a variable name and a function inner. The function inner logs the value of name to the console. We then return the function inner from outer and store it in a variable called closure. Finally, we call the closure function.

"Hussaini"
Enter fullscreen mode Exit fullscreen mode

When we call closure(), it logs the value of name to the console, even though name is not defined within the closure function itself. This is because closure is a closure that has access to the variables of the outer function, even though outer has already returned.

This may seem like a small and insignificant detail, but closures can be incredibly powerful when used correctly. They allow you to create functions that are both flexible and efficient, and can help you write code that is easier to read and maintain.


How to Use Closures?

Now that we know what closures are and how they work, let's look at some examples of how to use them in your code.

1. Creating Private Variables
One common use of closures is to create private variables. In JavaScript, all variables defined within a function are accessible to any nested functions within that function. This means that if you define a variable in a function, any functions defined within that function can also access that variable. For example:

function outer() {
 var name = "Hussaini";
 function inner() {
 console.log(name);
 }
 inner();
}
outer();
Enter fullscreen mode Exit fullscreen mode

In this code, we define a function called outer that contains a variable name and a function inner. The function inner logs the value of name to the console. We then call the inner function from within the outer function.

"Hussaini"
Enter fullscreen mode Exit fullscreen mode

When we call outer(), it logs the value of name to the console, because inner has access to the name variable. However, this also means that any other functions defined within outer would also have access to the name variable, which may not always be desirable.

To create a private variable that is only accessible to theinnerfunction, we can use a closure. Here's an example:

function outer() {
 var name = "Hussaini";
 function inner() {
 console.log(name);
 }
 return inner;
}
var closure = outer();
closure();
Enter fullscreen mode Exit fullscreen mode

In this code, we define a function called outer that contains a variable name and a function inner. The function inner is returned from outer instead of being called directly. We then store the returned function in a variable called closure. Finally, we call the closure function.

"Hussaini"
Enter fullscreen mode Exit fullscreen mode

When we call closure(), it logs the value of name to the console, just like before. However, because name is defined within the outer function and not directly accessible outside of it, it is effectively a private variable that is only accessible through the closure created by outer.

2. Creating Callback Functions
Another common use of closures is to create callback functions. A callback function is a function that is passed as an argument to another function and is executed when the original function completes. Callback functions can be used for a variety of purposes, such as handling user input or responding to server requests.

Here's an example of how to create a callback function using closures:

function calculate(num1, num2, operation) {
 var result = operation(num1, num2);
 console.log("Result: " + result);
}
function add(num1, num2) {
 return num1 + num2;
}
function subtract(num1, num2) {
 return num1 - num2;
}
calculate(5, 10, add);
calculate(5, 10, subtract);
Enter fullscreen mode Exit fullscreen mode

In this code, we define a function called calculate that takes three arguments: num1, num2, and operation. The operation argument is expected to be a function that takes two numbers and returns their result. We then use the operation function to calculate the result of num1 and num2, and log the result to the console.

We also define two additional functions called add and subtract that take two numbers and return their sum and difference, respectively. We then call the calculate function twice, passing in the add and subtract functions as the operation argument each time.

When we run this code, we should see the following output:

//Result: 15
//Result: -5
Enter fullscreen mode Exit fullscreen mode

This is because the calculate function is using the operation function passed in as an argument to perform the calculation. This allows us to use different functions for different calculations without having to rewrite the calculate function every time.

3. Memoization
Finally, closures can also be used for memoization, which is a technique for optimizing function performance by caching the results of expensive calculations. Memoization can be especially useful when dealing with recursive functions that perform the same calculations multiple times.

Here's an example of how to use closures for memoization:

function fibonacci() {
 var cache = {};
 function calculate(n) {
 if (n in cache) {
 return cache[n];
 } else {
 if (n <= 1) {
 return n;
 } else {
 var result = calculate(n - 1) + calculate(n - 2);
 cache[n] = result;
 return result;
 }
 }
 }
 return calculate;
}
var fib = fibonacci();
console.log(fib(10));
console.log(fib(15));
console.log(fib(20));
Enter fullscreen mode Exit fullscreen mode

In this code, we define a function called fibonacci that returns another function called calculate. The calculate function takes a single argument n and uses memoization to calculate the nth Fibonacci number.

We use a closure to create a cache object that stores the results of expensive calculations. If the result of the calculation for a given n value is already in the cache, we return that result instead of performing the calculation again. Otherwise, we calculate the result using a recursive call to calculate, store the result in the cache, and then return the result.

Finally, we call the fibonacci function to get the calculate function, and store it in a variable called fib. We then call the fib function three times with different values to calculate the 10th, 15th, and 20th Fibonacci numbers.

When we run this code, we should see the following output:

//55
//610
//6765
Enter fullscreen mode Exit fullscreen mode

This is because the calculate function is using memoization to avoid performing the same calculations multiple times. This makes the function faster and more efficient.


Conclusion

In conclusion, closures are a powerful feature of JavaScript that allow you to create functions with private variables and maintain state between function calls. Closures can also be used for creating callback functions and for memoization. By understanding how closures work, you can write more efficient and flexible JavaScript code.

My name is Hussaini Ahmed, I am a front end developer. I also write about front end languages, frameworks and latest technologies. Iโ€™d loved to hear your thought on this article. Feel free to drop a comment below or reach out to me via:

Upwork
Github
WhatsApp
Twitter
LinkedIn

Top comments (2)

Collapse
 
fruntend profile image
fruntend

ะกongratulations ๐Ÿฅณ! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up ๐Ÿ‘

Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ • Edited

A closure is a function...

A closure is not a function. A closure is "the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment)". This is a subtle distinction, but it needs to be made to stop people ending up with the mistaken belief that a closure is a special kind of function.

a closure is created when a function is defined inside another function,

This isn't correct. ALL functions have an associated closure, regardless of whether they were created inside another function.

From MDN:

In JavaScript, closures are created every time a function is created, at function creation time.

I'm not sure why so many people get this wrong.