What are closures?
Closures are a way to let a function have persistent, private variables - that is, variables that only one function knows about, where it can keep track of info from previous times that it was run.
Let's break this down.
Private variables
Giving a function a private variable is easy: just make a local variable inside it. For instance, in Javascript:
function annoyingAlert(){ var x = "I'm private! "; x += "Nobody can see me outside this function."; alert(x); x = "Yep, still private."; }
Although x can't be changed from outside our function, it is very short-lived: each time the function finishes, x gets thrown away. When the function runs again, it is re-created. The second string it gets assigned will never be seen in the alert.
Persistent Variables
These are also pretty easy. Just make a... (sinister music) global variable.
nastyGlobalX = 1; function annoyingAlert(){ var alertString = "I can count! "; alertString += "I'm currently at " + nastyGlobalX; alert(alertString); nastyGlobalX++; }
Now you've got persistence - each time you call annoyingAlert(), you'll get a new number. But since we're using a global variable, it could get changed by a different function. Our counting would be ruined!
Enter closures
This is where closures come in. They work like this:
1. Make an outer, "function maker" function.
2. Declare a local variable inside it.
3. Declare an inner function inside the outer one.
4. Use the outer function's variable inside the inner function.
5. Have the outer function return the inner function
6. Run the function, and assign its return value to a variable
For example:
function functionMaker(){ var x = 1; function innerFunction(){ alert(x); x++; } return innerFunction; } var counterFunction = functionMaker(); counterFunction(); counterFunction();
See! Magic!
Wait, you look confused. OK, let's back up.
A Closer Look
OK, look at the example above. What gets assigned to the variable called 'counterFunction?'
At first glance, you might say it's the functionMaker function. But it's not - we said 'functionMaker()', with parentheses, which means 'run that function and put its return value here.' When functionMaker runs, it ends by returning innerFuction. So counterFunction = innerFunction.
The magic happens at step 5. When functionMaker returns innerFunction, its life is over. Like a used tissue, it has served its purpose and will be thrown away. That includes any local variables that it contained.
But wait! Its innerFuction can't be thrown away, because we've assigned it to a variable, counterFunction. We still need it! And counterFunction() uses the local variable that functionMaker() declared (which was called 'x'). So that variable can't be thrown away either.
But where is that variable? It's in the twilight zone. From counterFunction()'s perspective, it was declared in the parent scope and persists from one run to the next, just as though it were a global variable.
But from any other function's perspective, it's a local variable, declared inside functionMaker(). They can't touch it or see it.
Yeeha! Now we've got a variable that's both private and persistent. It's a place for counterFunction to keep its record, safe from meddling and from garbage collection.
What's it good for?
But... so what? What can we do with that?
Well, a closure could be used to generate, for example, a function called newUserID(). Every time you call that function, you'd get a new ID. But in most situations, you'd want to take care of something like that in a database.
A closure would only help if you need a variable to stick around while your program is running, but no longer.
Next post, I'll show an example where that's exactly what you'd need.