When to Use Closures?
A closure is useful in hiding implementation detail in JavaScript. In other words, it can be useful to create private variables or functions – closure is valid in multiple levels of inner functions.
The following example shows how to create private functions & variable:
Example 1
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
alert(counter.value()); // 0
counter.increment();
counter.increment();
alert(counter.value()); // 2
counter.decrement();
alert(counter.value()); // 1
In the above example, increment()
, decrement()
and value()
becomes public function because they are included in the returned object literal, whereas changeBy()
function becomes a private function because it is not returned and only used internally by increment() and decrement().
Closures vs. Global Scope
Closures are like creating global variables in the global scope and a function that accesses them, but then enclosing this whole environment inside of a function.
Example 1: Closure is similar to the global scope
var passed = 3;
var addTo = function () {
var inner = 2;
return passed + inner;
};
console.dir(addTo());
As you can see, function addTo
is a normal top level function, and it has access to an outer variable passed
– a global variable. Consequently, addTo
is a function declared inside a scope – in this case, the global scope – similar to a closures.
Example 2: User closures instead of globals
// Trying to solve the global variable usage issue using a one-level function doesn't work.
let global1 = function (newval) {
let num = 0;
if (newval) {
num = newval;
}
return num;
}
global1(); // 0
global1(5); // 5
global1(); // 0 again; that's not useful..
// Using a two-level function (i.e. Closure) helps get the variable re-definition issue out of the scope.
const makeGlobalVar = function () {
let num = 0;
return function (newval) {
if (newval) num = newval;
return num;
}
}
const num2 = makeGlobalVar();
num2(); // 0
num2(5); // 5
num2(); // 5 still.
num2(5)
is the equivalent of assigning a value to a global variable, (i.e. this num2 = 5
).
And num2()
is the equivalent of getting the value of a global variable (i.e. this num2
).
The gist that you need to get from all of this, is that a closure is good for protecting values from conflict and unintended change. Thus, closures are used in distributing JavaScript modules and libraries – each library uses closures to prevent variable conflicts.