Closure and its Application in easiest way possible.
Pravin Poudel
Posted on March 13, 2020
+1 like for your willingness to learn closure. Closures can seem really daunting, to begin with, I know they were for me. Once you get the hang of them, you'll instantly be a much better coder.
For more on topics like this, you can visit icodeeveryday.
Every Interviewer's favorite topic is Closure. Let's dive here on What is Closure and why do we need it. Before Jumping into Closure, first, let's find what is Lexical Scoping.
Lexical Scoping :
Lexical Scoping is the popular convention of Variable scoping in many programming languages. Another approach is dynamic scoping which we will not discuss here. Javascript follows the Lexical scoping approach. In Lexical Scoping, the scope of a variable is based on the block where the variable is defined. It can only be called from the block of code where it is defined. Lexical scope is also known as static scope because the scope of a variable is fixed in a block in which it is defined.
In order to resolve variable, javascript starts at the innermost scope and searches outward until it finds the variable it was looking for.
So, the Inner function can access the variable on outer function and global variable whereas outer function can only access its own variable and Global variable.
Let's try with an example:
function outer() {
let a = 3;
function inner() {
console.log(a);
}
inner()
}
outer();
The output of the above code is 3.Here outer() function conatain inner function inner()and when outer() is called inner function is executed which can access variable a inside outer function i.e outside inner function block.
This is the output:
Moreover, this is the shortest definition, I could ever think of:
Closure in Javascript :
function outer() {
let a = 3;
return function inner() {
console.log(a);
}
}
let inner_function = outer();
console.log(inner_function());
In the code above, outer() function return the inner() function without being executed. It is common to think that since the outer function is already executed the variable must have been dropped so, the inner function using variable a in the last line of code must bring error. But, javascript functions form closure. Closure basically means the combo of function and it's Lexical environment when it was created. In the lexical environment, there are variables that were in scope of the function when the closure was created. So, though the function outer() is already called, the closure allows us to use variable a in inner().
Let's see a more beautiful example by Mozilla
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
This is not only good code to demonstrate closure, but also a good example to depict one of the major applications of closure. In the code above, we have a function that takes an argument and returns an inner function which also takes an argument.
In the code,
var add5 = makeAdder(5);
var add10 = makeAdder(10);
This creates a closure add5 and add10 when the makeAdder(5) and makeAdder(10) function is called. This return a function and the lexical environment where x is 5 and 10 respectively. What I am trying to advocate is that both closures have separate lexical environment. So, it is not necessary that multiple closures should share same lexical environment.
So, if this is a cool thing in javascript, what might be the possible example or application where you can use closure though not limited.
Application 1 :
Emulate Private scope for variable and functions:
Valuable usage of closure is a hiding variable. Unlike other languages where we can declare private and public variables and function, there is nothing like that to hide function and variable in Javascript. We can hide variables and function in javascript with the help of Closure.
For example:
function Car() {
var speed = 0;
return {
accelerate: function() {
speed++;
}
}
}
var car = new Car();
car.accelerate();
Here, in code above speed is only accessible by accelerate otherwise, it is hidden. It is only exposed to accelerate. In general, closure has allowded to use hidden variable internally.
Another powerful example that present us the way function can be emulated private with help of closure is again taken here from mozilla
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // 0.
counter.increment();
counter.increment();
console.log(counter.value()); // 2.
counter.decrement();
console.log(counter.value()); // 1.
In the example code above, three functions counter.increment, counter.value and counter.decrement share same lexical environment. The lexical environment is created when the self-invoking function (anonymous function) is called or executed. There are many functions and variables in the anonymous functions. privateCounter variable and changeBy() function are private where as the object method returned by the anonymous function is public. You can't access either of these private members from outside the anonymous function. You can only access the private function and variable inside it with public functions.
Those three public functions are closures that share the same lexical environment. Thanks to JavaScript's lexical scoping, they each have access to the privateCounter variable and the changeBy function.
Another example is in the counter
<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>
Here, in the code counter variable is inaccessible from outside i.e it is a private variable that can be accessed only by updateClickCount which is the reference of the function returned . Since it is a private variable we can stay assured that it cannot be tempered from other parts of code as it isn't exposed globally and vulnerably.
Application number 2:
Closures are very important in functional programming as they are used for two concepts — partial application and currying. :
Providing less argument to a function than the function has expected is a partial application of a function.
We call a function with fewer arguments than it expects and It returns a
function that takes the remaining arguments. And this is called Partial
Application of Functions.
There is always a topic of discussion on Partial function and currying. I wanna diminish this with one line definition of both:
# Partial Application :
A function is partially applied when it is given a fewer argument than it expects and returns a new function expecting the remaining arguments. Partial application fixes one or more arguments inside the returned function
# Currying :
A function is curried when it takes one argument at a time and returns a new function expecting the next argument.
let's write a small code first and we will approach how closure is involved in this partial application of a function:
const addFourNumber = (a, b, c, d) => a + b + c + d;
//normal function invocation
const norm_result = addFourNumber(1, 2, 3, 4);
//console output is "The result of normal function invocation is 10"
console.log("The result of normal function invocation is " + norm_result);
//This code will bind 1 and 2 to a and b and return
//partial function and closure with a and b already
//assigned, and c and d are required to be passed.
const partialaddFourNumber = addFourNumber.bind(null, 1, 2);
//PartialaddFourNumber is a reference to the partial function
//returned that is wanting the parameter for c and d. So when
//partialaddFourNumber is called with partialaddFourNumber(3,4)
//it return the result i.e 1+2+c+d which is 10
const partial_result = partialaddFourNumber(3, 4);
//The result of the console is "The result of a
//partially applied function is 10" which is the same
//with the previous console output.
console.log("The result of a partially applied function is " + partial_result);
This block of code is an example code to demonstrate currying to the very same function addFourNumber() from the above code. Let's look through the code and try to understand how currying is basically closure.
Before jumping to code, let's remember first that the function is gonna accept each argument one at a time and returning a function each time until it has all the arguments and then return the value of the function body
const addFourNumber = (a, b, c, d) => a + b + c + d;
function add(a) {
return (b) => {
return (c) => {
return (d) => {
return a + b + c + d ;
}
}
}
}
//invoke a curried function
const result = add(1)(2)(3)(4);
console.log(result);
//which is same as calling as this below :
const result = add(1);
const result2 = result(2);
const result3 = result2(3);
const result5 = result3(4);
console.log(result5);
If you are confused and can't understand bind() and had hard time to understand chunk of code above currying's section, have a look at the makeAdder() code we went through earlier. Our previous code of adder is :
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
This is also a partially applied function example code which is the same as binding in the above code. Here, the code itself has makeAdder() function which returns closure of inner function.
The main benefit to closures is you can "partially apply" a function using a closure, then pass the partially applied function around, instead of needing to pass the non-applied function, and any data you'll need to call it (very useful, in many scenarios).
In Other Words:
Closures are really useful when we are dealing with higher-order functions especially when we want to communicate state.
That's it so when the Interview presents the code with the structure like above, remember what we learned here.
It's what I have right now in my mind. I will update this if anything new comes to my mind. Let me know if I missed something.
Thanks for reading.
Don' forget to follow me on Twitter. I post interesting code and articles there to keep you updated and rejuvenated.
That's it.
Have a good day, Take Care and Cheers !!!!
Posted on March 13, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 16, 2020