In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
In JavaScript, closures are defined as inner functions that have access to variables and parameters of outer function even after the outer function has returned.
Suppose, you want to count the number of times user clicked a button on a webpage.
For this, you are triggering a function on onclick
event of button to update the count of the variable
<button onclick="updateClickCount()">click me</button>
You could use a global variable, and a function to increase the counter:
var counter = 0;
function updateClickCount() {
++counter;
// Do something with counter
}
But, the pitfall is that any script on the page can change the counter, without calling updateClickCount()
.
Now, you might be thinking of declaring the variable inside the function:
function updateClickCount() {
var counter = 0;
++counter;
// Do something with counter
}
But, hey! Every time updateClickCount()
function is called, the counter is set to 1 again.
Thinking about nested functions?
Nested functions have access to the scope "above" them.
In this example, the inner function updateClickCount()
has access to the counter variable in the parent function countWrapper()
:
function countWrapper() {
var counter = 0;
function updateClickCount() {
++counter;
// Do something with counter
}
updateClickCount();
return counter;
}
This could have solved the counter dilemma, if you could reach the updateClickCount()
function from the outside and you also need to find a way to execute counter = 0
only once not everytime.
Closure to the rescue! (self-invoking function):
var updateClickCount = (function(){
var counter = 0;
return function(){
++counter;
// Do something with counter
}
})();
The self-invoking function only runs once. It sets the counter
to zero (0), and returns a function expression.
This way updateClickCount
becomes a function. The "wonderful" part is that it can access the counter in the parent scope.
This is called a JavaScript closure. It makes it possible for a function to have "private" variables.
The counter
is protected by the scope of the anonymous function, and can only be changed using the add function!
<script>
var updateClickCount = (function(){
var counter = 0;
return function(){
++counter;
document.getElementById("spnCount").innerHTML = counter;
}
})();
</script>
<html>
<button onclick="updateClickCount()">click me</button>
<div> you've clicked
<span id="spnCount"> 0 </span> times!
</div>
</html>
Reference: JavaScript Closures
I've used closures to do things like:
a = (function () {
var privatefunction = function () {
alert('hello');
}
return {
publicfunction : function () {
privatefunction();
}
}
})();
As you can see there, a
is now an object, with a method publicfunction
( a.publicfunction()
) which calls privatefunction
, which only exists inside the closure. You can not call privatefunction
directly (i.e. a.privatefunction()
), just publicfunction()
.
It's a minimal example, but maybe you can see uses to it? We used this to enforce public/private methods.
The example you give is an excellent one. Closures are an abstraction mechanism that allow you to separate concerns very cleanly. Your example is a case of separating instrumentation (counting calls) from semantics (an error-reporting API). Other uses include:
Passing parameterised behaviour into an algorithm (classic higher-order programming):
function proximity_sort(arr, midpoint) {
arr.sort(function(a, b) { a -= midpoint; b -= midpoint; return a*a - b*b; });
}
Simulating object oriented programming:
function counter() {
var a = 0;
return {
inc: function() { ++a; },
dec: function() { --a; },
get: function() { return a; },
reset: function() { a = 0; }
}
}
Implementing exotic flow control, such as jQuery's Event handling and AJAX APIs.
JavaScript closures can be used to implement throttle and debounce functionality in your application.
Throttling puts a limit on as a maximum number of times a function can be called over time. As in "execute this function at most once every 100 milliseconds."
Code:
const throttle = (func, limit) => {
let isThrottling
return function() {
const args = arguments
const context = this
if (!isThrottling) {
func.apply(context, args)
isThrottling = true
setTimeout(() => isThrottling = false, limit)
}
}
}
Debouncing puts a limit on a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called."
Code:
const debounce = (func, delay) => {
let debouncing
return function() {
const context = this
const args = arguments
clearTimeout(debouncing)
debouncing = setTimeout(() => func.apply(context, args), delay)
}
}
As you can see closures helped in implementing two beautiful features which every web application should have to provide smooth UI experience functionality.
Yes, that is a good example of a useful closure. The call to warnUser creates the calledCount
variable in its scope and returns an anonymous function which is stored in the warnForTamper
variable. Because there is still a closure making use of the calledCount variable, it isn't deleted upon the function's exit, so each call to the warnForTamper()
will increase the scoped variable and alert the value.
The most common issue I see on Stack Overflow is where someone wants to "delay" use of a variable that is increased upon each loop, but because the variable is scoped then each reference to the variable would be after the loop has ended, resulting in the end state of the variable:
for (var i = 0; i < someVar.length; i++)
window.setTimeout(function () {
alert("Value of i was "+i+" when this timer was set" )
}, 10000);
This would result in every alert showing the same value of i
, the value it was increased to when the loop ended. The solution is to create a new closure, a separate scope for the variable. This can be done using an instantly executed anonymous function, which receives the variable and stores its state as an argument:
for (var i = 0; i < someVar.length; i++)
(function (i) {
window.setTimeout(function () {
alert("Value of i was " + i + " when this timer was set")
}, 10000);
})(i);
In the JavaScript (or any ECMAScript) language, in particular, closures are useful in hiding the implementation of functionality while still revealing the interface.
For example, imagine you are writing a class of date utility methods and you want to allow users to look up weekday names by index, but you don't want them to be able to modify the array of names you use under the hood.
var dateUtil = {
weekdayShort: (function() {
var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
return function(x) {
if ((x != parseInt(x)) || (x < 1) || (x > 7)) {
throw new Error("invalid weekday number");
}
return days[x - 1];
};
}())
};
Note that the days
array could simply be stored as a property of the dateUtil
object, but then it would be visible to users of the script and they could even change it if they wanted, without even needing your source code. However, since it's enclosed by the anonymous function which returns the date lookup function it is only accessible by the lookup function so it is now tamperproof.
There is a section on Practical Closures at the Mozilla Developer Network.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With