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();
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"
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();
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"
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 theinner
function, 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();
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"
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);
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
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));
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
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:
Top comments (2)
Π‘ongratulations π₯³! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up π
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.
This isn't correct. ALL functions have an associated closure, regardless of whether they were created inside another function.
From MDN:
I'm not sure why so many people get this wrong.