An Introduction to JavaScript Closures
Javascript provides the functionality of nested functions, returning a function, etc.
These nested functions have access to the scope of its parent function.
Consider the snippet below:
function counter() {
let value = 0;
return function(incrementer) {
value += incrementer;
console.log(value)
}
}
let myCount = counter();
myCount(4); // 4
myCount(4); // 8
In the above snippet, we declare a function called counter()
.
In counter()
‘s function scope, we have a variable value and an anonymous function which gets returned by counter()
.
The anonymous function also has its own scope. incrementer
is present in the scope, also, value
which was contained in the outer scope is modified in this scope.
The red block contains items in the counter
scope while the blue block represents items in the scope of the anonymous function.
All items in the blue block can access items in the red block because the blue block is encapsulated in the red block.
This is why mycount
can be called multiple times and still has access to value
which was declared in the outer scope.
Even after the execution of the red scoped function, we can still access and modify variables declared in the red block from the blue block. This is because the function, counter, create a closure.
As defined by MDN, a closure is the combination of a function and the lexical environment within that function.
Closure gives you access to a function’s scope from an inner function, even after the outer function is done executing.
In the example above, the inner anonymous function had access to value
which was created in the outer scope — counter. It should be noted that value cannot be accessed outside the counter function, hence the closure cannot be accessed from the outside.
Uses of Closure
Most modern languages have private variables, but in javascript, there are no private variables.
Since functions create closures which can only be accessed by functions defined in them, these closures can help create a private space for functions and variables.
Utilizing the private space created by closures, we can have private variables and functions in javascript.
function table(data) {
let storage = [];
let size = 0;
if(Array.isArray(data)) {
storage = [...data];
size = storage.length;
}
return {
addItem(data) {
storage.push(data);
size++;
},
removeItem(data) {
let index = storage.findIndex(data);
if(index !== -1) {
storage.splice(index, 1);
size--;
}
},
getAll() {
return [...storage];
},
getSize() {
return size;
}
}
}
In the example above, we create a table
function which has 2 variables declared in its scope: storage, size. Storage, stores the items in the table, while size counts the number of items in the table. We don’t want users to be able to access these two important variables, so we don’t let them, using the closure created by table
.
We want the users to be able to add items to the table, remove items from the table and check the size of the table without having access to where these sensitive data is stored. To do that, we return an object in the table function. This object has all the methods required for the user to perform all his required actions which were listed above.
The addItem
method enables the user to add items to the table, by simply pushing the data to the storage and incrementing size to reflect the new addition.
Similarly, removeItem
enables the user to remove an item from the table. You pass the item you want to remove, and the function removes the item from the storage.
This protection is done so the user doesn’t have direct access to storage, thereby giving the user-controlled access to the storage by making it private and providing simple methods which can be used to access it.
The getAll
method is provided so the user can access everything in the table. We are spreading out the item so that we create a new copy of the data. Returning the array directly will make the user able to modify the content of storage since objects in javascript are passed by reference.
The last method here is getSize
. It allows the user access to the number of items in the table.
Conclusion
The closure is an important concept to understand and utilize in javascript, which if understood, can help out in numerous situations.
Closures are also an important concept to understand before learning about higher-order functions. You can learn more about higher-order functions here.
You can read more about closures on FreeCodeCamp.