These features allow developers to create robust and efficient code by controlling the visibility and lifetime of variables and functions.
In other words, a closure “closes over” its surrounding state, preserving the values of its variables and functions.
On the other hand, lexical scoping is a mechanism in which a variable’s scope is determined by its position within the source code. The scope of a variable is defined by the location of its declaration in the code, and the variables and functions declared in the outer scope are accessible within the inner scope.
Imagine you are planning a surprise party for your friend, and you want to send out invitations. You have a list of guests and their addresses, but you don’t want to reveal the addresses to anyone else.
So, you write a function that takes in the guest list and returns a new function that can be used to send out invitations to the guests.
The returned function has access to the guest list, but no one else does. This is an example of a closure, where the returned function “closes over” the guest list variable and has access to it even after the outer function has returned.
This way, you can send out the invitations without revealing the addresses to anyone else. The guest list is kept private and secure within the closure, and only the returned function can access it.
In the above code, we have defined an
outer function that declares a
variable x and defines an
inner function that logs the value of x.
outer() function returns the
inner() function, and we store it in a variable closure.
When we call
closure(), it outputs the value of
x, which is
10. Here, the
inner() function has closed over its surrounding state, preserving the value of x even after the
outer() function has returned.
Let’s check another example, Consider you want to create a counter which will increment every time you call the function.
makeCounter() function closes over the
count variable and returns a function called
getCurrentCount() which uses this lexical scoped variable count and adds one to it and returns the updated count.
Now every time you call the
getCurrentCount() function, it incrementally returns the count value by
remembering what was the last value of count and adding one to it.
When you attach an event listener to a DOM element, it creates a closure that has access to the variables and functions declared in the outer scope.
This mechanism allows you to create efficient and flexible code that responds to user input in real-time.