What is a closure, currying and memoization in javascript
It is a concept for implementing lexical scope binding in javascript by using functions. Closure
is created when inner functions are able to access the variables of outer function. What closure does is it remembers the state of the function, even after the function as returned. If we have to create a closure
, we have to define a function inside another function and return so, that inner function will be having access to outer function variables.
Lexical environment is a reference to the outer functions scope and is part of the every function execution context.
Unlike a normal function, closure
allows the function to access the stored variables through closures copy of their references even when it is called outside the function. As every function will be having a reference to its lexical environment that's how it sees and can access variables declared outside the function.
Examples of closure in javascript
Here createClosure
is a instance of function innerFunction and it is created when outerFunction is called. innerFunction maintains a reference to its lexical environment, so in environment consists any variables which were in scope at the time of closure creation so variable outerVariable exists. Example:
In the example, mutiply
is called and creates a lexical environment in which mutiplyByTimes
parameter value is bound to 3 and function is returned. thrice remembers this environment so when it is called by passing 5 to number parameter, it is multiplied.
How closures can be used in javascript?
Private methods using closures
JavaScript does not provide a way of making private like any other programming languages and it can be done using closures. Here private methods useful for restricting access and managing the global namespaces. In object oriented programming it is similar to data hiding and encapsulation and that is achieved using closures
. Lets see an example
In the above example we have two private methods: privateCounter
and privateMethodToChangeValue
and three public methods increment, decrement and getValue. Here two counters maintains their own lexical environment and we can see that from example. counter
1 variable increment is not affecting counter2
variable. So here we cannot access private methods outside the createCounter
function but instead we can access public methods which are returned from createCounter
function.
Event oriented
Here onClick creates closure and closes over BACKGROUND_COLOR which is in global scope.
More Examples of closure
Example 1
This example shows one of the problem with closures
Here the output is 2 2
but we are expecting output as 1 and 2. Here two closures
are created by the for loop but each one shares the same lexical environment because we have declared i
with var
. When we try to do console.log(i)
in setTimeout
it will be last value of i i.e 2, because the loop has already run its course by that time. We can fix this by using let
We have used var
keyword instead of let
so, closure
binds the block scoped variable meaning new lexical environments are created for each loop.
Example 2
Another example of let. Closure
maintains reference to the original variables. The stack frame stays alive in memory even after the outer function exits.
It is a optimization technique used to store the function calls in object
and return the cached result when the same input is passed again. It is a process of caching
results when we provide the same big inputs and return same output without heavy computations. Lets take an example
In the above example we are trying to square the number. So we have created an object square.cache where we will storing as key value
pair. Line 2 we are checking in cache object for that particular key. If it is not present we will compute it and store it in square.cache object. If the key
exists it won't compute and what ever it is already stored in cache same it will return.
We will consider one more example for Fibonacci with closure and memoization :
In the above example we are calculating fibonacci for ’n’. recursiveFib
and fibonacci()
is in the same scope and recursiveFib
is a closure
. So cache
can be accessed in the inner scope.
Currying is transforming a function of multiple parameters into sequence of functions that each take a single parameter. Curry method works by creating closure that holds the original function and arguments to curry. Example
In the above example, we are passing add() to curry() in step 1.
In step 1, it returns this function
Next call we will passing one more parameter curry(sum)(1)
, then the result will be
Then if we pass second parameter curry(sum)(1)(2)
, we will getting the final output.
References
Originally published at https://www.allaboutjavascriptworld.com on July 4, 2020.