24

How can one understand closures in Javascript?

In general terms, a closure is a function bound to one or more external variables. When it is called, the function is able to access these variables. In JavaScript, closures are often implemented when functions are declared inside another function. The inner function accesses variables of the parent one, even after the parent function has terminated

In this statement, "a closure is a function bound to one or more external variables", does it mean we can do this : var myFun = Function(msg){...}; is it correct ?

What does it mean "even after the parent function has terminated"?

Jess
  • 23,901
  • 21
  • 124
  • 145
user595234
  • 6,007
  • 25
  • 77
  • 101
  • In your example, `var myFun = Function(msg){...};`, you are assigning a function to a variable, which is not a closure by itself. – Jess Apr 04 '13 at 02:33

3 Answers3

9

closure is a function bound to one or more external variables

An example of this concept is that the function bar is bound to the external variables x, y, and z:

function foo(x, y) {
  var z = 3;

  return function bar(a, b, c) {
    return (a + b + c) * (x + y + z);
  };
}

var closure = foo(1, 2);
closure(5, 6, 7); // (5 + 6 + 7) * (1 + 2 + 3) = 24

The variable closure refers to the inner function bar returned from the call to foo. Invoking closure is like reentering the scope within foo, which gives visibility into all of foo's local variables and parameters.

even after the parent function has terminated

This means that after foo is executed, the returned function stored in the closure variable persists the state of foo. You can even create multiple independent closures by invoking foo again:

var closure = foo(1, 2);
closure(5, 6, 7); // (5 + 6 + 7) * (1 + 2 + 3) = 24

var closure2 = foo(0, 0);
closure2(5, 6, 7); // (5 + 6 + 7) * (0 + 0 + 3) = 21

/* closure2 does not affect the other closure */
closure(5, 6, 7); // (5 + 6 + 7) * (1 + 2 + 3) = 24
Ian
  • 50,146
  • 13
  • 101
  • 111
Rick Viscomi
  • 8,180
  • 4
  • 35
  • 50
  • It doesn't persist the state of `foo` so much as creates a special scope containing (1) the returned function and (2) all the external variables referenced at the time of the return (`x`, `y`, and `z`). This special scope is called a closure. Case in point... if you had another var defined in `foo` that was not referenced in the return function, it would not exist in the closure scope. – Daedalus Mar 27 '13 at 19:09
  • I think we're saying the same thing in different ways. "persist" = create special scope, "state of `foo`" = everything in scope to `foo` at the time. – Rick Viscomi Mar 27 '13 at 19:14
  • But that is not correct. "everything in the scope of `foo`" will not be persisted. Only things referenced inside returned function. It is not just that `foo`s scope sticks around. An entirely new scope is created and THAT is what a closure is. – Daedalus Mar 27 '13 at 19:25
  • Point taken. I still think "state of foo" is a succinct and accurate description of the closure mechanics. – Rick Viscomi Mar 27 '13 at 19:29
  • succinct yes. accurate no. But, I've beaten the semantic horse enough. It is probably close enough for the OPs needs :) – Daedalus Mar 27 '13 at 19:30
  • @mkoryak - it matters to the programmer who wants to understand what a closure actually is, which was the question. If the question was concerning a particular implementation that happened to use closure, I would have just left the point alone as it would not have mattered :) – Daedalus Apr 04 '13 at 02:15
  • way to go and reply right about the same time i wrote this off and decided to make a question out of it – mkoryak Apr 04 '13 at 02:21
  • 1
    @RickViscomi! Hi! Your code example is missing a closed curly brace! `}`. – Jess Apr 04 '13 at 02:29
  • 1
    An interesting counter example has been brought to my attention, so it seems your answer was indeed fully correct: http://stackoverflow.com/questions/15801471/deeper-understanding-of-closure-in-javascript – Daedalus Apr 04 '13 at 02:57
  • 1
    Thanks Jessemon for bringing it up and Ian for making the edit. Daedalus, I didn't fully understand the point you were making until I read the counter example in that question you referenced. I'm glad you stuck your neck out; we're all a little wiser for it :) – Rick Viscomi Apr 04 '13 at 15:02
  • Just an observation-`even after the parent function is terminated` ... How the closure is able to do it? Answer: Browser keeps Lexical Environment of the parent function with all its properties/variables in memory until there is an inner function which refers to it. – Lakshmi Swetha G Feb 01 '17 at 08:23
3

Your interpretation of external variables is incorrect. It really means it can do this:

function make_closure() {
  var x = 20;
  return function() {
    console.log(x);
  };
}

var closure = make_closure();
closure(); // Displays 20
Razvan Zamfir
  • 4,209
  • 6
  • 38
  • 252
Dark Falcon
  • 43,592
  • 5
  • 83
  • 98
  • 2
    i think the important point is why this is a closure. The closure is created around `x`, which usually would fall out of scope when you returned from the `make_closure()` call, but is forced to be kept around because the function returned references it. – Daedalus Mar 27 '13 at 19:01
3

I'm not sure where you are quoting from, but it sounds like it's referencing when the parent function has finished running.

Dusty
  • 1,053
  • 2
  • 11
  • 24