Skip

Closure Exposure
May 8, 2007 4:19 PM   Subscribe

Can someone please explain javascript closures to me in plain english? Closures for Dummies makes me feel like a dummy. What are closures and why would I want to use them? And most importantly, what is a real world example of where they would be really useful. I have no formal CS background, so if you mention CS terms I might get confused.
posted by kaizen to Computers & Internet (21 answers total) 7 users marked this as a favorite
 
The videos here are excellent and should answer your question and more. Start with "The JavaScript Programming Language." I think part 3 or 4 deals with closures and has a good real-world example.
posted by sanko at 4:26 PM on May 8, 2007


strings and numbers can be stored as variables, sent to functions as arguments and returned from functions. For example:

alert("some text") sends the string "some text" to the alert function, doSomething(5) sends the integer 5 to the doSomething function.

Closures are a fancy way of saying functions can be treated the same way as strings and integers. Specifically, they can be stored in variables, sent to functions and and returned from functions.

Why might you want to do this? Suppose you created a javascript library that would do something fancy that would take some time, such as connecting to a remote server. Your users might want an action to happen after your function completes. You could use closures to do this by letting the user pass you a function and later calling this function. For example,

function libraryCall(url, doneFunction)
{
// do something fancy and long
// like calling "url"
doneFunction()
}

Your users could then call this function using the following

var myDoneFunction = function() { alert("done"); }

libraryCall("http://www.metafilter.com", myDoneFunction);

which would cause "done" to be shown when the libraryCall function completed.
posted by null terminated at 4:33 PM on May 8, 2007


Er, you're close null terminated. Closures are the binding of a function to its scope. Merely using functions as values is not sufficient to create a closure.

A pseudocode example

function foo(x) {
return function (y) { return x+y }
}

foo(6) returns a function that will add 6 to its argument and return the value:

xyzzy = foo(6)
xyzzy(34) => 40

Closures let you, in a way, create function generators. I'm over simplifying here but that's what you want.

Why would you use them? Well, until you get used to them you probably wouldn't. Not all languages have them and so many of us pros don't even think about them very often. They do come up in python, lisp, and scheme quite a bit. Javascript isn't usually used to implement large systems so sophisticated stuff like closures doesn't come up much.
posted by chairface at 4:46 PM on May 8, 2007


Yeah, I should have mentioned that. I thought talking about free variables, etc might be too confusing.
posted by null terminated at 4:52 PM on May 8, 2007


null terminated, that is not strictly an example of a closure, that is just an example of functions as first class objects.

A closure is pretty much 'functions as first class objects' that retain access to any variables that were available when the function was created.

function buildAlert(string) {
return function() {alert(string);}
}

Notice how the inside function doesn't define 'string', it inherits 'string' from it's containing function. Long after buildAlert() has finished running, the function it returned will still have access to the 'string' variable as the variable was when the function was created.

var foo_alert = buildAlert("foo");
var bar_alert = buildAlert("bar");

libraryCall("http://www.metafilter.com", foo_alert);
libraryCall("http://www.example.com", bar_alert);

See: Wikipedia - Closure (computer science). Even if the evil CS is mentioned, it's not that hard to read.

Closures really help you build functions that return other functions that are constructed on the fly.
posted by zengargoyle at 5:00 PM on May 8, 2007


doh!, I should learn to preview... :)

Add Perl to the list of languages with closures. Once you get used to them, you'll wonder how you ever lived without them.
posted by zengargoyle at 5:07 PM on May 8, 2007


zengargoyle writes "Notice how the inside function doesn't define 'string', it inherits 'string' "

Please don't use "inherit" in this context; you're going to confuse anyone trying to do OOP.
posted by orthogonality at 5:28 PM on May 8, 2007


shhhhush, I was trying to avoid CS speak for the OP's sake. By the time you get to OOP you won't be confused by something like a closure. A closure inherits a scope of variables, an OOP inheritance inherits a scope of variables and a scope of methods, or maybe only a scope of methods depending on the language used, or a mish-mash of the two. Does your language support private class variables or not? Does your language even allow sub-classing, or does it support a 'final' attribute? It all depends...

A closure inherits the variable scope at the moment of creation, so that variable scope is available to the closure at runtime.
posted by zengargoyle at 5:56 PM on May 8, 2007


Read the first 50 pages of Programming Languages: Application and Interpretation. It will give you a solid CS-style understanding of closures, even if you start without a CS background.
posted by gmarceau at 5:58 PM on May 8, 2007


The concept of closures is pretty esoteric if you don’t get into the Computer Science theory. Essentially, it deals with variable scoping. Anonymous (lambda) functions and higher-order functions (which null terminated has demonstrated) often happen to appear coincidental to closures, but those are really different concepts.

Here’s a simple example. [The following depends on jQuery.] In it, several functions are created that are closures. In each of them, there is a reference to the variable meta, which was defined outside the body of the function. The function inherits the variable scoping environment in which it was defined. [The attentive reader will notice that this sample contains anonymous functions and higher-order functions, but as I said, those are not to understand closure.]


var select = document.createElement("select")
// ... add options, etc.

var meta = $(document.createElement("div"))
// ... add content, etc.

select.changeMeta = function()
{
meta.html($(this.options.item(this.options.selectedIndex)))
}


$(select).change(function()
{
var self = this
meta.fadeOut("fast",function()
{
self.changeMeta()
meta.fadeIn("fast")
}
})


Closures can also be used in JavaScript to create more encapsulated objects, which don’t expose "private" data. For example, a normal object allows outside code to access its member attributes:


var O = function( foo )
{
this.foo = foo
}
O.prototype.getFoo = function()
{
return this.foo
}

var myO = new O("bar")
alert(myO.getFoo()) // alerts "bar"
myO.foo = "quux"
alert(myO.getFoo()) // alerts "quux"


With a closure, you prevent outside code from being able to modify the data:


var O2 = function( foo )
{
this.getFoo = function() { return foo }
}

var myO = new O("bar")
alert(myO.getFoo()) // alerts "bar"
// myO doesn’t have a "foo" attribute, so it cannot be changed!


Another use for closures is to implement “partial function application,” as chairface demonstrates. That involves passing less than the full number of arguments to a function that takes multiple arguments, or even rearranging the order of a function’s arguments. For example, the Math.pow function takes two arguments, the first being the base and the second being the exponent:


var x = 10
var x3 = Math.pow(x,3) // x3 = 10^3 = 1000


Suppose you wanted to cube numbers frequently and you want to create a convenience function cube that simply takes the base as a single argument. To get there, you can create a generic, partially applied function raise that takes an exponent as a single argument, which when invoked returns another function that takes the base as a single argument and computes the value of the exponent.


var raise = function( n )
{
return function( base ) { return Math.pow(base,n) }
}
var cube = raise(3)

var x = 10
var x3 = cube(x) // x3 = 10^3 = 1000


posted by ijoshua at 7:26 PM on May 8, 2007


Thanks for the corrections to my post. I learned quite a bit from this thread.
posted by null terminated at 7:50 PM on May 8, 2007


Hmm, I cam across this link today. Maybe it'll be helpful?
posted by bkudria at 8:15 PM on May 8, 2007


“In it, several functions are created that are closures.”

To clarify, in JavaScript, all functions are closures over the environtment in which they are defined: code within the body of any JS function may manipulate* variables which are defined outside the body at the time the function is defined. There is no need to make this effect explicit.

* I say manipulate here, because the “dynamic” scoping rules of JavaScript allow a closure to change the value of a free variable:


x = 0;
f = function() { return x; }
g = function() { x = 1; return f(); }
alert(g()) // alerts "1"


In the above example, the function g changes the value of x, which is not in its local scope. The same value of x is seen by both f and g.
posted by ijoshua at 8:17 PM on May 8, 2007


I remember the first dozen or so times I read about closures. I'd read a description, it would make some sort of sense, and then I would think, "okay, sure, but what the fuck is being closed?" And they never said. Which made me think it was supposed to be so obvious they didn't need to say. And this led to me racking my brains for long periods of time and getting so frustrated that I forgot what a closure actually was.

Eventually I just started treating the word "closure" as a word like "flarble," i.e., a completely made-up word. The fact that it resembles an English word appears to be coincidental. It seems to mean something to some people, but hardly anyone comes out and says what exactly is being closed.
posted by kindall at 8:22 PM on May 8, 2007


kindall: As in understand it, the local environment is being closed up and packaged.
posted by bkudria at 8:27 PM on May 8, 2007


Well, yes, but if you close it, you can't use it anymore! Like when you close a file, it means you're done with it, not that you want to use it again.
posted by kindall at 8:32 PM on May 8, 2007


Ok, so yes, the 'close' part is a bit misleading. A mathematical closure is the smallest set that is closed under a given operation. A set is closed under an operation is if the result of that operation on members of the set is also always a member of the set.

For example, integers are closed under addition. Any integer plus any other integer will always be an integer.

In Computer Science, it's referring to packaging up the local environment, including any locally defined variables, and packing them up with the function. The closure is basically a function combined with the local environment. When the closure is evaluated, it can access that environment, whether it exists any more or not.

'Closure' is used because the function has access to not the global data and not just the local function data, but a combination of the two: all the local data, plus any global data referenced in the function as it was defined when the closure's parent function is evaluated.

I hope that helps clear it up!
posted by bkudria at 8:44 PM on May 8, 2007 [1 favorite]


It's closed like a (ziploc) bag. A bag containing variables that the function needs to run. And once it's closed you can kick it around, and not worry that the variables are going to fall out. That's how I think of it.
posted by breath at 8:52 PM on May 8, 2007


'Closure' is used because the function has access to not the global data and not just the local function data, but a combination of the two

See, most people, when they see the word "because," expect what follows to explain what came before the "because" -- in this case, why the word "closure" is used. That sentence is exactly the sort of wording that made me think it was supposed to be obvious and why I figured closures were hard.

The bit about "closed sets" in mathematics is a nice touch, since it doesn't seem to me to relate in any obvious way to the computer science definition, yet you have included it in the exact place a reader would expect to find an introduction to the concept.

Anyway, I figured out what a closure was a while back, and can see where I might use them, but like I said, I learned what they were despite the name, which I had to treat as opaque and unrelated to the actual concept.
posted by kindall at 8:59 PM on May 8, 2007


I only mentioned the bit about the name because it seems likely to me that it is the sort of thing that might well be causing a problem for kaizen.
posted by kindall at 9:02 PM on May 8, 2007


kindall: fair enough. My explanation makes sense to me, but I was never lauded as one who explains things well, although I like to think so.
posted by bkudria at 9:15 PM on May 8, 2007


« Older I have some questions about Pa...   |  [ObviousFilter?] Why haven't p... Newer »
This thread is closed to new comments.


Post