JavaScript functions provide closure -- a property that makes JavaScript functions both expressive and powerful. Closure is a binding that allows functions to be bound to their definition and in this regard, preserve the data, with which they are bound, even beyond their definition.
Let us understand this a little bit more. Since JavaScript functions are objects, they get to keep the context in which they are defined. This behavior is unlike many other languages, where when we invoke a function, then the stack defines variables internal to that function and once the function execution is complete, the stack removes those variables. In JavaScript, those local variables can linger on!
Let us use a simple example to understand a little bit more about closure. In the example that follows, we create a function and pass its return value to the varFunctionDummy variable. This anonymous function has an internal function, funcMagicKnower() and when we invoke the outer function, it simply returns the internal function. Since we invoke the function as soon as we define it (note the "()" after the end of the function block), varFunctionDummy in fact points to the funcMagicKnower. So, the outer function is invoked only once when we assign its return value to the varFunctionDummy but since the inner function gets assigned to varFunctionDummy, we can invoke varFunctionDummy later and due to this, the lifespan of the internal function becomes longer.
Now, the internal function accesses a global variable (magicKnower) and a local variable that is local to the outer function (magicAction). When we invoke this function via varFunctionDummy, we find two neat behavior of closure.
First, even though varFunctionDummy now is the internal function funcMagicKnower(), it still is able to access the magicAction variable that was defined only within the outer function. And, this happens even though we had invoked the outer function earlier and is not invoked in the current context.
Second, when we add a local variable magicKnower and also have a global variable of the same name and next, when we print this variable as part of the internal function, then when we print this value from the internal function, its value is same as the value that we assigned it in the function scope. Next, even though we change the value of the global magicKnower variable, the internal function is still bound to the value that was present at the time it was defined!
<!doctype html> <html> <div id="idDiv"></div> <script type="text/javascript"> // Get a handle of the div element. var elem = document.getElementById("idDiv"); var magicKnower = "The Dark Lord"; var varFunctionDummy = (function () { var magicKnower = "Wizards"; var magicAction = "Do Magic"; function funcMagicKnower() { elem.innerHTML += magicKnower + " " + magicAction; }; return funcMagicKnower; }()); // Invoke the function. varFunctionDummy(); // Prints "Wizards Do Magic". // Invoke the function after changing magicKnower variable. magicKnower = "The Evil Lord"; varFunctionDummy(); // Prints "Wizards Do Magic". </script> </html>
We can use the closure property to bind data to internal functions. As an example, in the example provided below, we use an object magicList that is internal to the outer function and bind it to an internal object. Next, we publish various methods of this object that allow us to manipulate the list object. Lastly, we return the internal object when the function is invoked and store this object as part of the magicInfo variable.
<!doctype html> <html> <div id="idDiv"></div> <script type="text/javascript"> // Get a handle of the div element. var elem = document.getElementById("idDiv"); function printObject (obj) { var prop = Object.getOwnPropertyNames(obj); for (var item in prop) { elem.innerHTML += prop[item] + " -- " + obj[prop[item]] + "<br>"; } elem.innerHTML += "<br>"; } var magicInfo = (function() { var magicList = {"Wizards": "Do Magic"}; var internalMagicObject = { add: function (magicName,magicAction) {magicList[magicName] = magicAction;}, lookup: function (magicName) {return magicList[magicName];}, printList: function () {printObject(magicList);}, }; return internalMagicObject; }()); // Print the magicInfo which holds the internalMagicObject. printObject(magicInfo); magicInfo.add("Dragons", "Fly and Spit Fire"); magicInfo.add("Goblins", "Do Mischief"); // Now, print the list. magicInfo.printList(); </script> </html>
Here is the output. The list though gets defined during the lexical definition of the function, once assigned to the variable magicInfo, the object internalMagicObject simply continues to exist. Also, the magicList object that is being used as part of the internalMagicObject. Thus, we can use closure to define data internal to a function and to continue using it beyond the function definition.
As is clear from the above example, we can use closure to create private variables. For example, in the above example, there is no way to manipulate the magicList object. The internalMagicObject provides three methods to add, lookup and to print the list.
We discuss two popular examples of function closures: bind and curry. With bind, we create a closure of a function with an object. With curry, we create a closure of a function with arguments.
Let us first describe bind.
The bind method is one of the inbuilt methods that are available with all Function objects via Function.prototype. With bind, a function creates a closure such that an object gets bound to the the function to create a new function. When we invoke the new function, the (earlier) bound function is treated as if it were a method of that object.
Let us see this as an example. This example (provided below) uses a dummy object (magicList) and a function (add()) to demonstrate the bind. After that, we call bind() to bind add() function to magicList and create a new function, magicAdd(). When we call magicAdd(), it works just as if it were a method of magicList object.
<!doctype html> <html> <div id="idDiv"></div> <script type="text/javascript"> // Get a handle of the div element. var elem = document.getElementById("idDiv"); // Trivial function to print an object. function printObject (obj) { var i = 0, prop = Object.getOwnPropertyNames(obj); for (var item in prop) { if ( i++ != 0) {elem.innerHTML += ", ";} elem.innerHTML += prop[item] + ": " + obj[prop[item]]; } } // Define an empty object. var magicList = {}; // Define a function that will bind the above object. function add(magicName, magicAction) {this[magicName] = magicAction;} // Bind object magicList to the function to create a new function, magicAdd. var magicAdd = add.bind(magicList); // Invoke the new function (should work as a method of magicList). magicAdd("Dragons", "Spit Fire"); magicAdd("Goblins", "Do Mischief"); printObject(magicList); // Prints "Dragons: Spit Fire, Goblins: Do Mischief". </script> </html>
When we print the object, the output shows that the object now has two name/value pairs. However, the printObject() does not print magicAdd() (or add()) as methods of this object. Thus, add() function is bound to the object via a closure but technically, it is not a method of this object.
Next, let us describe currying.
Currying allows us to bind a list of arguments to a function. When defining a new function, the closure binds these arguments to that of the original function as well. Thus, if we were to add a filler parameter to the add() function in the earlier example, we could pass an argument to the bind() call and this argument (or arguments) would be bound to the arguments of the function.
Let us understand this by rewriting the earlier example. The example that follows adds a new argument, "filler", to the add function. Next when we call bind(), immediately after the object, we also pass a string "can". Due to currying, the "can" value gets bound to the filler argument of the add() function. Note that the ordering is important. The "can" value would be bound to first argument. If we were to provide three arguments with the bind() call, then all of these three (in the same order) would be bound to the all the three arguments of the add() function.
<!doctype html> <html> <div id="idDiv"></div> <script type="text/javascript"> // Get a handle of the div element. var elem = document.getElementById("idDiv"); // Trivial function to print an object. function printObject (obj) { var i = 0, prop = Object.getOwnPropertyNames(obj); for (var item in prop) { if (i++ != 0) {elem.innerHTML += ", ";} elem.innerHTML += prop[item] + " " + obj[prop[item]]; } } // Define an empty object. var magicList = {}; // Define a function that will bind the above object function add(filler, magicName, magicAction) { this[magicName] = filler + " " + magicAction; } // Bind object magicList to the function to create a new function, magicAdd // The "can" value is bound to the "filler" argument of the add function var magicAdd = add.bind(magicList, "can"); // Invoke the new function (should work as a method of magicList) // Due to currying, there is no need to add "can" with every call! magicAdd("Dragons", "Spit Fire"); magicAdd("Goblins", "Do Mischief"); printObject(magicList); // Prints "Dragons can Spit Fire, Goblins can Do Mischief". </script> </html>