Closures are an immensely useful feature that Javascript has inherited from other languages. To be precise, closures come from the world of functional programming. Unfortunately, they’re not quite as mainstream as they could be (though they are much more popular now than they were, say, five years ago.) This creates a tendency to make them hard to grasp at first, since most programmers discover them only after they’ve gotten used to other methods. Anyhow, this isn’t a post about why Javascript has closures, or if they’re worth learning, and so forth. Instead, I’d just like to share a couple of cool tricks that I’ve noticed can be easily accomplished with the feature.
Closures in a Nutshell
Of course, to understand this post, you need to know at least the basics of closures. If you’re already comfortable with the concept, you can go ahead and skip this section; otherwise, listen up.
Essentially, a closure is the process of saving the state of a certain level of scope, so that it can be used outside of where it exists. To say it more simply, consider it like this: inside of a function, you declare a few local variables, and another function. This inner-function can access all the other local variables, because they exist in the same scope. But what happens if you return that function as a value? The main functions scope closes, and the locals are destroyed, right? If we call the returned function, it would try to access variables that don’t exist anymore…or do they? The fact is that they do. When that function was returned, the entire scope was saved, and now we can still use it outside of were it existed. This a closure. Nifty, eh?
Let’s look at a quick example to get our brains up to speed:
function someState() {
var someLocal = 3;
return function() { document.write(someLocal+' '); ++someLocal; }
}
var closure = someState();
closure(); // 3
closure(); // 4
closure(); // 5
Here, the variable closure is set to an anonymous function that references someLocal. Though someLocal doesn’t actually exist after someState() returns, closure is still able to be called, and returns in increasing intervals, because the inside state of someState() was saved in a closure. If this all makes sense, then “congratulations!” You’ve just passed the world’s shortest closure tutorial ever!
Okay! Let’s get started…
Use #1: Passing Parameters to a Callback Function
Have you ever had a function that you wanted to pass to setTimeout or setInterval, that needed parameters? You’ve probably said to yourself, how the heck can I get it access this information, if I can’t pass more than the function object itself? The most obvious solution is make some variables at a higher scope, but in a lot of cases (at least in mine), this leads to a lot of global data.
Closures give us a very easy, but elegant fix to this problem. Consider some simple event handling in a web page that utilizes the method:
function getMsgAlerter(msg) {
return function() { alert(msg); }
}
window.onresize = getMsgAlerter("The window was resized");
window.onscroll = getMsgAlerter("The page was scrolled");
You’ll notice we’ve solved a couple of problems here. Firstly, the callback functions are given data directly, so we eliminated the need for a separate global variable for each message we want to use. Secondly, getMsgAlerter() is now a generic generator. The need for a separate function for each callback is no longer present, since we can just make custom ones on the fly. Now, I admit getMsgAlerter() is a pretty pathetic example, but you probably see my point. This type of situation actually comes up quite often if you look for it, and is easy to handle with closures.
Use #2: Behind the Scenes Data Sharing
Another interesting use of closures, is to provide some static, but private data for a select few operations. Consider the idea of you writing some game engine components that are all separate objects. Each has it’s own purpose, and is moderately independent from the rest. But of course this is a game, and the components must communicate data, so, inevitably they’re going to need a place to share it. Here again closures give us a great alternative to global variables.
Consider this layout, based on one I saw in an HTML5 game recently:
myComponents = {
"drawer" : {
"freq" : 0, // the FPS frequency
"render" : function() { /* rendering code here*/ },
"setFreq" : function(newSpeed) { this.freq = newSpeed; }
},
"updater" : {
"freq" : 0, // the UpdatePS frequency
"update" : function() { /* updateing code here*/ },
"setFreq" : function(newSpeed) { this.freq = newSpeed; }
}
};
// OTHER CODE AND DEFINITIONS...
SOME_GAME_ENGINE.renderComponent = myComponents.drawer;
SOME_GAME_ENGINE.updaterComponent = myComponents.update;
Now, disregarding the specific APIs of the engine, we can see that each facet of game is made into an object, and passed to the main engine. This is great, since we can swap out single parts of our game without worrying about the rest. However, if–as we have stated–have components that are partially dependent upon each other, there has to be some extra data storage so they can communicate.
Let’s get a little context first. Look at our two components. You’ll notice they both have a freq variable, as well as a function to set it. Here, the frequency is how often we will call our components to do their work. Now, while rendering has to be a very fast and constant process, updating does not necessarily have to. The fact is that drawer should be working at a higher rate than updater.
But this introduces a new issue. If our rendering code is running at, say, twice the rate of our updating code, it would be rendering new data only half of the time. In a situation where processing the render is expensive (e.g. 3D graphics with lots of textures), it would make more sense to save and use the previous image until a new one is needed. Thus some extra state is needed here, so updater can tell the rest of the components that it has done it’s job, and the others can tell it when it needs do to it again. Once again, we’ll be using a closure to get the job done.
Take a look at this in action:
myComponents = function() {
var hasUpdated = false;
return {
"drawer" : {
"freq" : 0, // the FPS frequency
"lastRendr": null,
"render" : function() {
if(hasUpdated) {
var newImg = null;
/* render the new image here... */
draw(newImg);
lastRendr = newImg; /* save it*/
hasUpdated = false; /* reset */
}
else { draw(this.lastRendr); }
},
"setFreq" : function(newSpeed) { this.freq = newSpeed; }
},
"updater" : {
"freq" : 0, // the UpdatePS frequency
"update" : function() {
if(!hasUpdated) {
/* updating code here... */
hasUpdated = true;
}
},
"setFreq" : function(newSpeed) { this.freq = newSpeed; }
}
}
}();
Here, by wrapping our definitions in a function, we are able to use a closure to keep some static state that everyone can work with. We make a little boolean, called hasUpdated that represents the current state of our update process (whether it is done or not, or whether an update is needed yet). Whenever we update, it set to true, and when we render, if it’s true, we can process a new image, or otherwise just fall back on one we have saved.
As you can see, this method is very useful since we can have the rendering function run at extremely high speeds (even 60 FPS if we want) without over taxing any resources. Nifty, huh?
Use #3: Caching
This use was actually inspired by a post by David Chambers, so kudos to him for the idea.
Anyways, the idea is pretty simple. For example, just suppose that you’re making expensive AJAX requests to a server-side script that has to do a lot of processing. Every web developer knows that the least time spent on the backside, the better. Many times, browsers can help by caching, but we can’t really depend on this since users might be able to turn if off, or it may behave differently in different browsers. Thus, a simple script like this could really be an efficiency-nightmare:
// I love jQuery when it comes to AJAX
$.ajax({
"url" : "reallySlowPHP.php",
"data" : { "someData" : someValue},
"dataType" : "text"
"success": function() { /* Present result to user*/ }
});
Closures give us a very nifty way to create behind the scenes caching. Specifically, it allows us to memoizize the result so we don’t need to recompute it every time the function is called. Let’s take a look at it:
var cachedQuery = (function(){
var cache = new Array();
return function(query) {
if(cache[query]) {
return cache[query];
}
else {
var result = null;
/* ...normal ajax call here... */
cache[query] = result;
};
};
})();
Quick, simple, and to the point, but it can make miles of difference when it comes to high-performance AJAX. This has the advantage of being private, so it won’t be overwritten by other functions, or queries to the same request with other parameters.
Use #4: Currying and Binding Parameters
Suppose you have a function like so:
// Most useless function, ever!
function foo(j, a, v, A, s, c, r, i, p, t) {
return (j+a+v+A)-(s+c+r+i+p+t);
}
In many libraries and APIs, functions can take many parameters, and to work correctly, we must pass them all in. But sometimes, we keep passing in the same parameter (say, a shared variable), and end up doing more typing, which leads to verbose code that’s hard to change and slower to interpret. Anyhow, closures can give us a nice way to make parameter lists smaller, and clearer.
Taking the function we mentioned earlier as an example, if the first four parameters are constants, we could create a curried function like so:
var A = 5;
var bar = (function(j, a, v, A){
return function(s, c, r, i, p, t) {
foo(j, a, v, A, s, c, r, i, p, t);
};
})(1, 45, 6, A);
bar(1, 2, 3, 7, 5, 6);
Our customized bar function is four parameters smaller, but could be reduced even more so if we wanted. Anyhow, this is a great use of closures, that can be used in many general situations, and costs very little performance wise.
Use #5: Extending Properties
When working with callbacks, or object properties in general, we sometimes want to allow them to be extended. That is, we want to preserve the current functionality it offers, but add more. Guess what! Closures to the rescue again!
We could create a function that receives and object, a property name, and function to add as an extension. Such as:
function extend(obj, prop, func) {
var old = obj[prop];
obj[prop] = function() {
old();
func();
}
}
Here we save the existing functionality in the variable old, and thanks to the closure, we are able assign the property a new function, but are still able to call the old function. This situation could be further expanded by allowing a person to pass in another object (say, args) that could contain arguments to any of the callbacks. This is good stuff, ain’t it?
Conclusion
The five examples that I have mentioned here are only scratching the surface of closures. The possibilities are infinite; it’s only so long before someone says “Hey, I realized we could do X with closures!”, and thus the world of programming evolves. It’s kind of exciting, isn’t it?
By the way, make sure you’re aware of the fact that everything mentioned here can apply to languages other than Javascript. Lua for example, is another great language that uses closures a lot; so you may want to look into it if you haven’t.
Anyhow, I hope this made you realize how powerful and fun closures can be, and how they can take a messy rat’s-nest of code, and make it as elegant as good poetry. Well, that’s if for this round, I hope to see you all next time.
Enjoy!
P. S. If you come up with some cool closure ideas that I didn’t mention here, make sure to leave a comment and share it with everyone.