What is a 'Closure'?

160,893

Solution 1

Variable scope

When you declare a local variable, that variable has a scope. Generally, local variables exist only within the block or function in which you declare them.

function() {
  var a = 1;
  console.log(a); // works
}    
console.log(a); // fails

If I try to access a local variable, most languages will look for it in the current scope, then up through the parent scopes until they reach the root scope.

var a = 1;
function() {
  console.log(a); // works
}    
console.log(a); // works

When a block or function is done with, its local variables are no longer needed and are usually blown out of memory.

This is how we normally expect things to work.

A closure is a persistent local variable scope

A closure is a persistent scope which holds on to local variables even after the code execution has moved out of that block. Languages which support closure (such as JavaScript, Swift, and Ruby) will allow you to keep a reference to a scope (including its parent scopes), even after the block in which those variables were declared has finished executing, provided you keep a reference to that block or function somewhere.

The scope object and all its local variables are tied to the function and will persist as long as that function persists.

This gives us function portability. We can expect any variables that were in scope when the function was first defined to still be in scope when we later call the function, even if we call the function in a completely different context.

For example

Here's a really simple example in JavaScript that illustrates the point:

outer = function() {
  var a = 1;
  var inner = function() {
    console.log(a);
  }
  return inner; // this returns a function
}

var fnc = outer(); // execute outer to get inner 
fnc();

Here I have defined a function within a function. The inner function gains access to all the outer function's local variables, including a. The variable a is in scope for the inner function.

Normally when a function exits, all its local variables are blown away. However, if we return the inner function and assign it to a variable fnc so that it persists after outer has exited, all of the variables that were in scope when inner was defined also persist. The variable a has been closed over -- it is within a closure.

Note that the variable a is totally private to fnc. This is a way of creating private variables in a functional programming language such as JavaScript.

As you might be able to guess, when I call fnc() it prints the value of a, which is "1".

In a language without closure, the variable a would have been garbage collected and thrown away when the function outer exited. Calling fnc would have thrown an error because a no longer exists.

In JavaScript, the variable a persists because the variable scope is created when the function is first declared and persists for as long as the function continues to exist.

a belongs to the scope of outer. The scope of inner has a parent pointer to the scope of outer. fnc is a variable which points to inner. a persists as long as fnc persists. a is within the closure.

Further reading (watching)

I made a YouTube video looking at this code with some practical examples of usage.

Solution 2

I'll give an example (in JavaScript):

function makeCounter () {
  var count = 0;
  return function () {
    count += 1;
    return count;
  }
}

var x = makeCounter();
x(); returns 1
x(); returns 2
...etc...

What this function, makeCounter, does is it returns a function, which we've called x, that will count up by one each time its called. Since we're not providing any parameters to x it must somehow remember the count. It knows where to find it based on what's called lexical scoping - it must look to the spot where it's defined to find the value. This "hidden" value is what is called a closure.

Here is my currying example again:

function add (a) {
  return function (b) {
    return a + b;
  }
}

var add3 = add(3);
    
add3(4); returns 7

What you can see is that when you call add with the parameter a (which is 3), that value is contained in the closure of the returned function that we're defining to be add3. That way, when we call add3 it knows where to find the a value to perform the addition.

Solution 3

First of all, contrary to what most of the people here tell you, closure is not a function! So what is it?
It is a set of symbols defined in a function's "surrounding context" (known as its environment) which make it a CLOSED expression (that is, an expression in which every symbol is defined and has a value, so it can be evaluated).

For example, when you have a JavaScript function:

function closed(x) {
  return x + 3;
}

it is a closed expression because all the symbols occurring in it are defined in it (their meanings are clear), so you can evaluate it. In other words, it is self-contained.

But if you have a function like this:

function open(x) {
  return x*y + 3;
}

it is an open expression because there are symbols in it which have not been defined in it. Namely, y. When looking at this function, we can't tell what y is and what does it mean, we don't know its value, so we cannot evaluate this expression. I.e. we cannot call this function until we tell what y is supposed to mean in it. This y is called a free variable.

This y begs for a definition, but this definition is not part of the function – it is defined somewhere else, in its "surrounding context" (also known as the environment). At least that's what we hope for :P

For example, it could be defined globally:

var y = 7;

function open(x) {
  return x*y + 3;
}

Or it could be defined in a function which wraps it:

var global = 2;

function wrapper(y) {
  var w = "unused";

  return function(x) {
    return x*y + 3;
  }
}

The part of the environment which gives the free variables in an expression their meanings, is the closure. It is called this way, because it turns an open expression into a closed one, by supplying these missing definitions for all of its free variables, so that we could evaluate it.

In the example above, the inner function (which we didn't give a name because we didn't need it) is an open expression because the variable y in it is free – its definition is outside the function, in the function which wraps it. The environment for that anonymous function is the set of variables:

{
  global: 2,
  w: "unused",
  y: [whatever has been passed to that wrapper function as its parameter `y`]
}

Now, the closure is that part of this environment which closes the inner function by supplying the definitions for all its free variables. In our case, the only free variable in the inner function was y, so the closure of that function is this subset of its environment:

{
  y: [whatever has been passed to that wrapper function as its parameter `y`]
}

The other two symbols defined in the environment are not part of the closure of that function, because it doesn't require them to run. They are not needed to close it.

More on the theory behind that here: https://stackoverflow.com/a/36878651/434562

It's worth to note that in the example above, the wrapper function returns its inner function as a value. The moment we call this function can be remote in time from the moment the function has been defined (or created). In particular, its wrapping function is no longer running, and its parameters which has been on the call stack are no longer there :P This makes a problem, because the inner function needs y to be there when it is called! In other words, it requires the variables from its closure to somehow outlive the wrapper function and be there when needed. Therefore, the inner function has to make a snapshot of these variables which make its closure and store them somewhere safe for later use. (Somewhere outside the call stack.)

And this is why people often confuse the term closure to be that special type of function which can do such snapshots of the external variables they use, or the data structure used to store these variables for later. But I hope you understand now that they are not the closure itself – they're just ways to implement closures in a programming language, or language mechanisms which allows the variables from the function's closure to be there when needed. There's a lot of misconceptions around closures which (unnecessarily) make this subject much more confusing and complicated than it actually is.

Solution 4

Kyle's answer is pretty good. I think the only additional clarification is that the closure is basically a snapshot of the stack at the point that the lambda function is created. Then when the function is re-executed the stack is restored to that state before executing the function. Thus as Kyle mentions, that hidden value (count) is available when the lambda function executes.

Solution 5

A closure is a function that can reference state in another function. For example, in Python, this uses the closure "inner":

def outer (a):
    b = "variable in outer()"
    def inner (c):
        print a, b, c
    return inner

# Now the return value from outer() can be saved for later
func = outer ("test")
func (1) # prints "test variable in outer() 1
Share:
160,893
Ben
Author by

Ben

Currently working at MajorBoost Inc. solving healthcare's communications problems one phone call at a time. Formerly: Worked on HoloLens for Microsoft Was the CTO at a location based games company Tech lead and programmer for Ubisoft and Sony Computer Entertainment Dot-bomb survivor and one of the many people who, independently, created something like AJAX but didn't come up with the cool name.

Updated on July 08, 2022

Comments

  • Ben
    Ben almost 2 years

    I asked a question about Currying and closures were mentioned. What is a closure? How does it relate to currying?

  • Lazer
    Lazer almost 14 years
    okay, thanks to your answer, I think that I finally have some idea what closure is about. But there is one big question: "we can use a linked list to store the state of the namespace at the time of function definition, allowing us to access variables that otherwise would no longer be in scope." Why do we want to access variables that are out of scope? when we say let x = 5, we want x to be 5 and not 3. What is happening?
  • Kyle Cronin
    Kyle Cronin almost 14 years
    @Laser: Sorry, that sentence didn't make much sense, so I updated it. I hope it makes more sense now. Also, don't think of the linked list as an implementation detail (as it's very inefficient) but as a simple way of conceptualize how it could be done.
  • user
    user about 12 years
    IDK, what language (probably F#) you've used in above language. Could please give above example in pseudocode? I'm having hard time to understand this.
  • Kyle Cronin
    Kyle Cronin about 12 years
  • Matt Fenwick
    Matt Fenwick over 11 years
    It's not just the stack -- it's the enclosing lexical scope(s) that are preserved, regardless of whether they're stored on the stack or the heap (or both).
  • Admin
    Admin about 11 years
    @KyleCronin Great example, thanks. Q: Is it more correct to say "the hidden value is called a closure", or is "the function that hides the value is the closure"? Or "the process of hiding the value is the closure"? Thanks!
  • Kyle Cronin
    Kyle Cronin about 11 years
    @RobertHume Good question. Semantically, the term "closure" is somewhat ambiguous. My personal definition is that the combination of both the hidden value and the enclosing function's use of it constitutes the closure.
  • Admin
    Admin about 11 years
    @KyleCronin Thanks -- I have a Scheme mid-term on Monday. :) Wanted to have the "closure" concept solid in my head. Thanks for posting this great answer to OP's question!
  • DPM
    DPM over 10 years
    Could I have an example of how this works in a library like JQuery as stated in the 2nd to last paragraph? I didn't totally understand that.
  • superluminary
    superluminary over 10 years
    Hi Jubbat, yes, open up jquery.js and take a look at the first line. You'll see a function is opened. Now skip to the end, you'll see window.jQuery = window.$ = jQuery. Then the function is closed and self executed. You now have access to the $ function, which in turn has access to the other functions defined in the closure. Does that answer your question?
  • Jon Cooke
    Jon Cooke almost 10 years
    It should be noted that extending language or host objects is generally considered a bad thing as they are part of the global namespace
  • artemonster
    artemonster over 8 years
    A question: why (let (count 0) ...) is not overriding previously set value on second call?
  • Kyle Cronin
    Kyle Cronin over 8 years
    @artemonster (let ((count 0) ...) is only called once, when make-counter is called. Make-counter, when called, returns a function with a reference to the value of count that it creates. If you call make-counter again, a new count variable is created and a new closure with a reference to it is returned.
  • SasQ
    SasQ about 8 years
    Why is this minused? It is actually much more "on the right track" with that distinction into free variables and bound variables, and pure/closed functions and impure/open functions, than most of the other clueless answers in here :P (discounting for confusing closures with functions being closed).
  • soundyogi
    soundyogi about 8 years
    I have no Idea, really. This is why StackOverflow sucks. Just look at the source of my Answer. Who could argue with that?
  • chandra_cst
    chandra_cst over 7 years
    @superluminary Thanks for the great explanation. But I've a question with respect to Java's support for closures. While I read that Java doesn't support closures, based on your explanation it seems like it does. Lets say, you have a public method that can create an instance of anonymous class, the anonymous class's implementation can use the function's local variables. Does this mean Java supports closures?
  • superluminary
    superluminary over 7 years
    @chandra_cst - I'm afraid I'm a little out of the loop with respect to Java.
  • Alexandros Spyropoulos
    Alexandros Spyropoulos over 7 years
    I recommend to change alert to console.log for easier testing in nodejs :). It helped me understanding better when I used all of your examples in there.
  • Jaakko Karhu
    Jaakko Karhu about 7 years
    I still have hard time understanding which defines the closure. In this example, the closure is function outer, right? Now is it so because it returns a function, because the returning of the function makes the closed variables persistent, or because it closes the var a? I am kind of asking here what makes closure a closure.
  • superluminary
    superluminary about 7 years
    @JaakkoKarhu - The closure scope is the scope containing the local variables that were accessible when the function was defined. The closure scope is preserved because the function in which is was created is preserved. A closure is the name we give to the structure whereby we keep hold of a function and therefore preserve its closure scope. Does that help?
  • Jaakko Karhu
    Jaakko Karhu about 7 years
    @superluminary Yes, this helps a lot. Thank you!
  • Abdullah Khan
    Abdullah Khan over 6 years
    I am from the Java background. That currying example is so damn lusciously beautiful.
  • Will Crawford
    Will Crawford about 6 years
    An analogy that might help beginners to this is a closure ties up all the loose ends, which is what a person does when they seek closure (or it resolves all necessary references, or ...). Well, it helped me to think of it that way :o)
  • Andrew
    Andrew almost 6 years
    I've been reading my textbook on this topic for two days and couldn't really grasp what was going on. Reading your answer took 4 minutes and it makes perfect sense.
  • eMBee
    eMBee over 5 years
    thanks for your answer. it would be more readable if you separated code from explanation. (don't indent lines that are not code)
  • SmokeRaven
    SmokeRaven over 5 years
    @superluminary this helped me understand as well. however, i am still having trouble seeing a real-world, but simple use case. is there a fairly common and simple instance of closure you've seen in the real world? am i right in thinking it's mainly about having a function that keeps state internally for whatever it was initialized with? thanks much!
  • superluminary
    superluminary over 5 years
    @BlissRage - one of the main purposes is for event handlers. When you set up your handler you have access to a bunch of local variables. Later though, when the handler is invoked, those variables may have changed or may no longer exist. Closure gives you a reliable runtime environment.
  • OZZIE
    OZZIE over 5 years
    "We can expect any variables that were in scope when the function was first defined to still be in scope when we later call the function, even if we call the function in a completely different context" => except if you call a function from an event like click then the closure is totally gone unless you have .bind(this) ...
  • superluminary
    superluminary over 5 years
    @OZZIE - you are confusing closure, which operates on local variables, with the this keyword, which operates on objects. In JavaScript, this is a hidden variable that is set when the function is called, it's not part of the closure. Bind simply permanently locks the value of this to a certain object. Closure, on the other hand, operates on variables, i.e. things that are declared using the var, cost or let keywords.
  • aaaaaa
    aaaaaa over 4 years
    so a closure is the function scope only if it remains persisted as a result of returning an inner function ? I'm confused as to what the 'closure' is exactly, like if you were to circle it in your example it'd be the content of 'outer' correct ?
  • Jason S.
    Jason S. over 4 years
    I've read a lot of definitions of closure over the years, but I think this one is my favorite so far. I guess we all have our own way of mentally mapping concepts like this and this one very much jives with mine.
  • Kai
    Kai almost 4 years
    SO doesn't suck and I never heard of the term "free variable"
  • ComDubh
    ComDubh almost 4 years
    It's hard to talk about closures without mentioning free variables. Just look them up. Standard CS terminology.
  • ComDubh
    ComDubh almost 4 years
    "Functions containing one or more free variables are called closures" is not a correct definition though -- closures are always first-class objects.
  • SIslam
    SIslam almost 4 years
    Your example is good but i am struggling to find the argument passing and operation order. e.g. If a+b=7 then, is 7=3+4 or is 7=4+3?
  • starriet
    starriet over 3 years
    I've seen whole lot of explanation from google, youtube, books, blogs, etc., and they all make sense and good ones, but I think this is the most logically clearest explanation.
  • user1063287
    user1063287 over 2 years
    do scenarios that create the dynamic of a closure always include 1) a copy of a function 2) where the original function is returning a function 3) where the original returned function is referencing a variable in its ‘outer’ lexical scope? i am just trying to define if, when looking at or writing code, there is a quick way to determine ‘oh a closure dynamic is going to occur here’.
  • user1063287
    user1063287 over 2 years
    @Sislam perhaps this will help: the value assigned to add3 is an evaluated function call, ie it’s value is a function with one parameter b. when you call add3(4) you are calling that function which ‘remembers’ the variable a and it’s value 3 even though a is outside of its function block and in some sense ‘no longer exists’. it is available because when add3 was declared, the variable a was accessible within the lexical scope of the inner function. the connection between the inner reference and outer variable, within its lexical scope, persists.
  • user1063287
    user1063287 over 2 years
    Is the global object a closure, because it encloses all nested variables and functions? perhaps not, because unlike the other ‘outer’ enclosing structures described, the global object can never be executed and ‘finished’?
  • superluminary
    superluminary over 2 years
    @user1063287 A closure is created whenever a function persists after its lexical scope has disappeared. Classic examples are callbacks. The function is created and passed to the DOM, or to a setTimeout, or to a Promise. All functions have a closure scope. That closure scope will be cleaned up by the garbage collector when the function is de-referenced. If the function is never de-referenced, that closure scope persists forever. I made a video that might help explain it, linked in the article.