I have been told that “Closure” is considered an important concept in functional programming, so I did some study on this topic, and would like to share it to you.
The following will be the outline:
2. What is a closure?
3. Implementations of closure
A function is a section of code that is predefined to perform a specific task.
a. With a function declaration：
b. With a function expression:
You might ask, what is the difference between the two?
The main difference is the way they are being evaluated by the browser.
When the browser begins to parse the code between the block, it goes through all the “function declarations” in the first pass, and restarts from the beginning to handle with the variables and function expressions subsequently.
With that said, the following script first correctly displays an alert, then shows an error message informing that ‘func’ is not a function since it has not yet been evaluated by the browser.
2. What is a closure?
According to the definition of closure on MDN
“Closures are functions that refer to independent (free) variables (variables that are used locally, but defined in an enclosing scope). In other words, these functions ‘remember’ the environment in which they were created.”
I believe an example would be more self-explanatory.
Now, in the script above, the body of the function “newAdder” is defined to return another function, which calculates the sum of “increment” and “num”.
What is a free variable then? A free variable is a kind of variable that is referred to, but not defined in the body of the function, nor in the parameters list. Thus we can infer that in the example above, in the aspect of the anonymous function, the variable “increment” is a free variable.
When we have declared a variable “addBy5Func” and assigned the result of executing function “newAdder” passing “5” as argument, variable “addBy5Fun” is now holding a reference to the function returned.
By the time we invoke “addBy5Func”(since it is a function), the parameter “num” gets the value 10 passed as argument, but it could not find the variable “increment” in the body or the parameter list, thus it tries to check for the value from the environment, and finds the value 5.
This corresponds to the definition of closure that the “environment” was returned along with the reference of the function itself. Roughly speaking the environment is a set of chained segments that consists of free variables.
3. Implementations of closure
I. Maintain certain values between method calls, e.g. a counter.
First of all, we are using an IIFE, which refers to “immediately-invoked function expression”, meaning that between the curly brackets is the body of an anonymous function that automatically runs when interpreted by the browser. This is beneficial to avoid creating too many global variables.
Within this IIFE, we define an array “someArray”, which is used by the anonymous function defined inside the function assigned to the variable “outputWithCounter”. Therefore, “counter” is a free variable since it is defined in the enclosing scope of the function that actually deals with the counter and console logging.
When we execute “outputWithCounter”, we get a returned function and assign it to variable “foo”. So now that variable can be considered a function, and when we execute the function, it logs a message with the counter incrementing its value by one on each call.
Notice that the free variable “counter” maintains its value since it is tied to the function returned by the function “outputWithCounter”, and that means no matter how many calls to the function returned is invoked, the free variable does not lose its value even when out of the defining scope.
II. Enforce private/public members
If you feel doubtful of what I’ve just mentioned, take a try. You’ll be astonished how this works, and it’s all because of the beauty of the concept “Closure”.
III. Currying !
The definition of currying can be found here
To put it briefly, it’s how we can translate functions with multiple arguments into a sequence of functions with a single argument.
In the example above, we first defined an IIFE. Inside its body, we define a new function named “curry” in the prototype of all functions, that is, “Function”(Starting with a capital is a convention indicating that a class is defined). What this function(curry) does is first obtain all the arguments passed in, parses them into an array, and saves it in a free variable relatively to the function that it is about to return. Finally when this function(curry) returns another function(anonymous), the body of the anonymous function concatenates the arguments from the environment(first pass) along with the new arguments passed later on(second pass) and executes the function.
With the definition of curry written, we then define a function “buildHtmlTag”, which takes “3” arguments, but instead of passing 3 altogether, we pass 2 first, then 1 later on. Take “buildTD” for example, we use function “curry”(inherited from the prototype) to pass “<td>” and “</td>” and made a function that only lacks the 3rd argument. In this way we can actually provide a template function that creates td elements along with the values, and the actually value can be assigned later on when we call the function.
To conclude, use closures in these situations:
1. When you would like to simulate access modifiers in object oriented programming like other programming languages such as C#, Java. In other words, implement encapsulation and abstraction.
2. When you want to pass information to functions that are executed in a delayed manner, e.g. setTimeout or event handlers.