Closures in Javascript
Understanding closures is like unlocking a hidden treasure within the world of JavaScript development. In this step-by-step guide, we’ll delve into the intricacies of closures, unraveling their mysteries and exploring the advantages they bring to your code.
What is a Closure ?
A closure in JavaScript is formed when a function is defined within another function, allowing the inner function to access the outer function’s variables. The inner function retains a reference to the outer function’s scope, even after the outer function has finished executing.
In simple terms, Function, along with its lexical scope, forms a closure
In this inner function is returned, as we can see that the outer function is executed, but if we go to execute the closureFn function, which actually contains the inner function will print X: 10, because it remembers its lexical scope, even after execution of its parent function.
In the screenshot, we can see a Closure object holds all the references of its outer variables.
Let’s see one more example with two inner functions:
- The magic here is in the closure created by the
inner
function. Even thoughouter
has finished executing, theinner
function still retains access to the variables in the lexical scope of its outer function (outer
), includingx
anda
. - When
closureFn
is invoked, it executes theinner
function, which logs the values ofx
anda
. The value ofx
is10
as expected, and the value ofa
is still accessible due to the closure, even though it is from the outermost functionoutest
.
Use Cases of Closure
- Data Encapsulation: Closures allow for the creation of private variables. By encapsulating variables within a function’s scope, they are not directly accessible from outside, promoting information hiding and reducing the risk of unintentional modifications.
2. Function Currying
Closures play a key role in function currying, a technique used in functional programming where a function is transformed into a sequence of functions, each taking a single argument. This is achieved through the use of closures to capture and remember the previously provided arguments. Let’s delve into an example to illustrate the concept:
In this example, curryAdd
is a currying function that takes an argument x
and returns a closure that takes another argument y
, which in turn returns another closure, taking the final argument z
. When all three arguments are provided, the closures are executed, and the sum of the arguments is returned.
The magic here lies in the closures preserving the values of x
and y
even after their respective functions have completed execution. This enables the creation of partially applied functions, allowing for a more flexible and modular approach to function composition.
First Closure: curryAdd(1) // Returns a closure with x = 1
Second Closure: curryAdd(1)(2) // Returns a closure with x = 1 and y = 2
Third Closure: curryAdd(1)(2)(3) // Returns a closure with x = 1, y = 2, and z = 3, then calculates the sum (1 + 2 + 3)
Disadvantages of closures
While closures are powerful, but we should consider memory management. Since closures retain references to their outer scope, they may keep objects in memory longer than expected. This can lead to potential memory leaks if not managed appropriately.
Conclusion
Closures in JavaScript provide an elegant way to create encapsulated and reusable code. Understanding how closures work is essential for mastering JavaScript and leveraging its full potential, particularly in scenarios involving data encapsulation, data hiding, function currying, etc. As we dive deeper into JavaScript development, closures will become a valuable tool for writing clean, modular, and efficient code.
Check out our other blog posts for more insights.