A function that returns a child function in which child function still has access to the properties / declarations of the parent function, even after the execution of the parent function is usually referred to as a Closure. For example,
According to the above example, even after the execution of ‘square’ function, the returning child function has access to the value of ‘x’. Here under we examine how this is possible.
One the hoisting is done, previous code block would looks like above.
For each execution of a function block a data structure called Lexical Environment (environment) is created. Each environment is stacked based on the execution context and it holds the outer environment / environment of the parent’s execution context and references to the values declared in the current execution context.
If we consider the above example where we have ‘square’ function declared in the global scope in which that function returns an object containing a function called ‘calc’. The environment stack would looks like below,
According to Wikipedia, Currying is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument. Simply, if a function takes three arguments and is curried, it is really three functions. Each function takes one argument and return a new function that takes the next argument until all arguments are received, then it returns the final result.
Consider a function that takes three arguments:
The equivalent curried function:
This is somewhat insane! returning nested functions as function takes more and more arguments. One option is to convert a normal function into a curried function, which is what mainly this article focuses here onward.
In concise, a Rest Parameter allows a function to receive a variable number of arguments and more details on this can be found in MDN: Rest Parameters.
The first time this function is called it only expects one argument, a function to curry. The args parameter will probably be an empty array on first invocation. Save the number of arguments it expects (argLength) to a local variable. Then return a function we define inside the curry function. When this function is invoked it concatenate the new args2 array with the old args array and check if it has received all the arguments yet. If so, it apply the original function and return the result. If not it recursively call the curry function, passing along all the new arguments which puts us back in the original position, returning the curried function to await more arguments.
With concepts like currying, it is much easier to abstract the logic and make clear and concise functions.