Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Monday, December 21, 2015

How do JavaScript closures work?

How do JavaScript closures work?


How would you explain JavaScript closures to someone with a knowledge of the concepts which make up them (for example, functions, variables and the like), but does not understand closures themselves?

I have seen the Scheme example given on Stack Overflow, and it did not help.

Answer by Joel Anair for How do JavaScript closures work?


JavaScript Closures for Dummies

Submitted by Morris on Tue, 2006-02-21 10:19. Community-edited since.

Closures Are Not Magic

This page explains closures so that a programmer can understand them ? using working JavaScript code. It is not for gurus or functional programmers.

Closures are not hard to understand once the core concept is grokked. However, they are impossible to understand by reading any academic papers or academically oriented information about them!

This article is intended for programmers with some programming experience in a mainstream language, and who can read the following JavaScript function:

function sayHello(name) {      var text = 'Hello ' + name;      var sayAlert = function() { alert(text); }      sayAlert();  }  

An Example of a Closure

Two one sentence summaries:

  • a closure is the local variables for a function ? kept alive after the function has returned, or
  • a closure is a stack-frame which is not deallocated when the function returns (as if a 'stack-frame' were malloc'ed instead of being on the stack!).

The following code returns a reference to a function:

function sayHello2(name) {      var text = 'Hello ' + name; // Local variable      var sayAlert = function() { alert(text); }      return sayAlert;  }  var say2 = sayHello2('Bob');  say2(); // alerts "Hello Bob"  

Most JavaScript programmers will understand how a reference to a function is returned to a variable (say2) in the above code. If you don't, then you need to before you can learn closures. A C programmer would think of the function as returning a pointer to a function, and that the variables sayAlert and say2 were each a pointer to a function.

There is a critical difference between a C pointer to a function and a JavaScript reference to a function. In JavaScript, you can think of a function reference variable as having both a pointer to a function as well as a hidden pointer to a closure.

The above code has a closure because the anonymous function function() { alert(text); } is declared inside another function, sayHello2() in this example. In JavaScript, if you use the function keyword inside another function, you are creating a closure.

In C, and most other common languages after a function returns, all the local variables are no longer accessible because the stack-frame is destroyed.

In JavaScript, if you declare a function within another function, then the local variables can remain accessible after returning from the function you called. This is demonstrated above, because we call the function say2() after we have returned from sayHello2(). Notice that the code that we call references the variable text, which was a local variable of the function sayHello2().

function() { alert(text); } // Output of say2.toString();  

Looking at the output of say2.toString(), we can see that the code refers to the variable text. The anonymous function can reference text which holds the value 'Hello Bob' because the local variables of sayHello2() are kept in a closure.

The magic is that in JavaScript a function reference also has a secret reference to the closure it was created in ? similar to how delegates are a method pointer plus a secret reference to an object.

More examples

For some reason, closures seem really hard to understand when you read about them, but when you see some examples you can click to how they work (it took me a while). I recommend working through the examples carefully until you understand how they work. If you start using closures without fully understanding how they work, you would soon create some very weird bugs!

Example 3

This example shows that the local variables are not copied ? they are kept by reference. It is kind of like keeping a stack-frame in memory when the outer function exits!

function say667() {      // Local variable that ends up within closure      var num = 666;      var sayAlert = function() { alert(num); }      num++;      return sayAlert;  }  var sayNumber = say667();  sayNumber(); // alerts 667  

Example 4

All three global functions have a common reference to the same closure because they are all declared within a single call to setupSomeGlobals().

function setupSomeGlobals() {      // Local variable that ends up within closure      var num = 666;      // Store some references to functions as global variables      gAlertNumber = function() { alert(num); }      gIncreaseNumber = function() { num++; }      gSetNumber = function(x) { num = x; }  }    setupSomeGlobals();  gIncreaseNumber();  gAlertNumber(); // 667  gSetNumber(5);  gAlertNumber(); // 5    var oldAlert = gAlertNumber;    setupSomeGlobals();  gAlertNumber(); // 666    oldAlert() // 5  

The three functions have shared access to the same closure ? the local variables of setupSomeGlobals() when the three functions were defined.

Note that in the above example, if you call setupSomeGlobals() again, then a new closure (stack-frame!) is created. The old gAlertNumber, gIncreaseNumber, gSetNumber variables are overwritten with new functions that have the new closure. (In JavaScript, whenever you declare a function inside another function, the inside function(s) is/are recreated again each time the outside function is called.)

Example 5

This one is a real gotcha for many people, so you need to understand it. Be very careful if you are defining a function within a loop: the local variables from the closure do not act as you might first think.

function buildList(list) {      var result = [];      for (var i = 0; i < list.length; i++) {          var item = 'item' + i;          result.push( function() {alert(item + ' ' + list[i])} );      }      return result;  }    function testList() {      var fnlist = buildList([1,2,3]);      // Using j only to help prevent confusion -- could use i.      for (var j = 0; j < fnlist.length; j++) {          fnlist[j]();      }  }  

The line result.push( function() {alert(item + ' ' + list[i])} adds a reference to an anonymous function three times to the result array. If you are not so familiar with anonymous functions think of it like:

pointer = function() {alert(item + ' ' + list[i])};  result.push(pointer);  

Note that when you run the example, "item2 undefined" is alerted three times! This is because just like previous examples, there is only one closure for the local variables for buildList. When the anonymous functions are called on the line fnlist[j](); they all use the same single closure, and they use the current value for i and item within that one closure (where i has a value of 3 because the loop had completed, and item has a value of 'item2'). Note we are indexing from 0 hence item has a value of item2. And the i++ will increment i to the value 3.

Example 6

This example shows that the closure contains any local variables that were declared inside the outer function before it exited. Note that the variable alice is actually declared after the anonymous function. The anonymous function is declared first; and when that function is called it can access the alice variable because alice is in the same scope (JavaScript does variable hoisting). Also sayAlice()() just directly calls the function reference returned from sayAlice() ? it is exactly the same as what was done previously, but without the temporary variable.

function sayAlice() {      var sayAlert = function() { alert(alice); }      // Local variable that ends up within closure      var alice = 'Hello Alice';      return sayAlert;  }  sayAlice()();  

Tricky: note also that the sayAlert variable is also inside the closure, and could be accessed by any other function that might be declared within sayAlice(), or it could be accessed recursively within the inside function.

Example 7

This final example shows that each call creates a separate closure for the local variables. There is not a single closure per function declaration. There is a closure for each call to a function.

function newClosure(someNum, someRef) {      // Local variables that end up within closure      var num = someNum;      var anArray = [1,2,3];      var ref = someRef;      return function(x) {          num += x;          anArray.push(num);          alert('num: ' + num +              '\nanArray ' + anArray.toString() +              '\nref.someVar ' + ref.someVar);        }  }  obj = {someVar: 4};  fn1 = newClosure(4, obj);  fn2 = newClosure(5, obj);  fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;  fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;  obj.someVar++;  fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;  fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;  

Summary

If everything seems completely unclear then the best thing to do is to play with the examples. Reading an explanation is much harder than understanding examples. My explanations of closures and stack-frames, etc. are not technically correct ? they are gross simplifications intended to help understanding. Once the basic idea is grokked, you can pick up the details later.

Final points:

  • Whenever you use function inside another function, a closure is used.
  • Whenever you use eval() inside a function, a closure is used. The text you eval can reference local variables of the function, and within eval you can even create new local variables by using eval('var foo = ?')
  • When you use new Function(?) (the Function constructor) inside a function, it does not create a closure. (The new function cannot reference the local variables of the outer function.)
  • A closure in JavaScript is like keeping a copy of all the local variables, just as they were when a function exited.
  • It is probably best to think that a closure is always created just on entry to a function, and the local variables are added to that closure.
  • A new set of local variables is kept every time a function with a closure is called (given that the function contains a function declaration inside it, and a reference to that inside function is either returned or an external reference is kept for it in some way).
  • Two functions might look like they have the same source text, but have completely different behaviour because of their 'hidden' closure. I don't think JavaScript code can actually find out if a function reference has a closure or not.
  • If you are trying to do any dynamic source code modifications (for example: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola'));), it won't work if myFunction is a closure (of course, you would never even think of doing source code string substitution at runtime, but...).
  • It is possible to get function declarations within function declarations within functions ? and you can get closures at more than one level.
  • I think normally a closure is the term for both the function along with the variables that are captured. Note that I do not use that definition in this article!
  • I suspect that closures in JavaScript differ from those normally found in functional languages.

Links

Thanks

If you have just learnt closures (here or elsewhere!), then I am interested in any feedback from you about any changes you might suggest that could make this article clearer. Send an email to morrisjohns.com (morris_closure @). Please note that I am not a guru on JavaScript ? nor on closures.

Answer by Florian Bsch for How do JavaScript closures work?


A closure is much like an object. It gets instantiated whenever you call a function.

The scope of a closure in JavaScript is lexical, which means that everything that is contained within the function the closure belongs to, has access to any variable that is in it.

A variable is contained in the closure if you

  1. assign it with var foo=1; or
  2. just write var foo;

If an inner function (a function contained inside another function) accesses such a variable without defining it in its own scope with var, it modifies the content of the variable in the outer closure.

A closure outlives the runtime of the function that spawned it. If other functions make it out of the closure/scope in which they are defined (for instance as return values), those will continue to reference that closure.

Example

function example(closure){      // define somevariable to live in the closure of example      var somevariable='unchanged';        return {          change_to:function(value){              somevariable = value;          },          log:function(value){              console.log('somevariable of closure %s is: %s',                  closure, somevariable);          }      }  }    closure_one = example('one');  closure_two = example('two');    closure_one.log();  closure_two.log();  closure_one.change_to('some new value');  closure_one.log();  closure_two.log();  

Output

somevariable of closure one is: unchanged  somevariable of closure two is: unchanged  somevariable of closure one is: some new value  somevariable of closure two is: unchanged  

Answer by Konrad Rudolph for How do JavaScript closures work?


Closures are hard to explain because they are used to make some behaviour work that everybody intuitively expects to work anyway. I find the best way to explain them (and the way that I learned what they do) is to imagine the situation without them:

var bind = function(x) {      return function(y) { return x + y; };  }    var plus5 = bind(5);  alert(plus5(3));  

What would happen here if JavaScript didn't know closures? Just replace the call in the last line by its method body (which is basically what function calls do) and you get:

alert(x + 3);  

Now, where's the definition of x? We didn't define it in the current scope. The only solution is to let plus5 carry its scope (or rather, its parent's scope) around. This way, x is well-defined and it is bound to the value 5.

Answer by Ali for How do JavaScript closures work?


Whenever you see the function keyword within another function, the inner function has access to variables in the outer function.

function foo(x) {    var tmp = 3;      function bar(y) {      alert(x + y + (++tmp)); // will alert 16    }      bar(10);  }    foo(2);

This will always alert 16, because bar can access the x which was defined as an argument to foo, and it can also access tmp from foo.

That is a closure. A function doesn't have to return in order to be called a closure. Simply accessing variables outside of your immediate lexical scope creates a closure.

function foo(x) {    var tmp = 3;      return function (y) {      alert(x + y + (++tmp)); // will also alert 16    }  }    var bar = foo(2); // bar is now a closure.  bar(10);

The above function will also alert 16, because bar can still refer to x and tmp, even though it is no longer directly inside the scope.

However, since tmp is still hanging around inside bar's closure, it is also being incremented. It will be incremented each time you call bar.

The simplest example of a closure is this:

var a = 10;  function test() {    console.log(a); // will output 10    console.log(b); // will output 6  }  var b = 6;  test();  

When a JavaScript function is invoked, a new execution context is created. Together with the function arguments and the parent object, this execution context also receives all the variables declared outside of it (in the above example, both 'a' and 'b').

It is possible to create more than one closure function, either by returning a list of them or by setting them to global variables. All of these will refer to the same x and the same tmp, they don't make their own copies.

Here the number x is a literal number. As with other literals in JavaScript, when foo is called, the number x is copied into foo as its argument x.

On the other hand, JavaScript always uses references when dealing with objects. If say, you called foo with an object, the closure it returns will reference that original object!

function foo(x) {    var tmp = 3;      return function (y) {      alert(x + y + tmp);      x.memb = x.memb ? x.memb + 1 : 1;      alert(x.memb);    }  }    var age = new Number(2);  var bar = foo(age); // bar is now a closure referencing age.  bar(10);

As expected, each call to bar(10) will increment x.memb. What might not be expected, is that x is simply referring to the same object as the age variable! After a couple of calls to bar, age.memb will be 2! This referencing is the basis for memory leaks with HTML objects.

Answer by Rakesh Pai for How do JavaScript closures work?


A closure is where an inner function has access to variables in its outer function. That's probably the simplest one-line explanation you can get for closures.

Answer by dlaliberte for How do JavaScript closures work?


This is an attempt to clear up several (possible) misunderstandings about closures that appear in some of the other answers.

  • A closure is not only created when you return an inner function. In fact, the enclosing function does not need to return at all in order for its closure to be created. You might instead assign your inner function to a variable in an outer scope, or pass it as an argument to another function where it could be called immediately or any time later. Therefore, the closure of the enclosing function is probably created as soon as the enclosing function is called since any inner function has access to that closure whenever the inner function is called, before or after the enclosing function returns.
  • A closure does not reference a copy of the old values of variables in its scope. The variables themselves are part of the closure, and so the value seen when accessing one of those variables is the latest value at the time it is accessed. This is why inner functions created inside of loops can be tricky, since each one has access to the same outer variables rather than grabbing a copy of the variables at the time the function is created or called.
  • The "variables" in a closure include any named functions declared within the function. They also include arguments of the function. A closure also has access to its containing closure's variables, all the way up to the global scope.
  • Closures use memory, but they don't cause memory leaks since JavaScript by itself cleans up its own circular structures that are not referenced. IE memory leaks involving closures are created when it fails to disconnect DOM attribute values that reference closures, thus maintaining references to possibly circular structures.

Answer by someisaac for How do JavaScript closures work?


Example for the first point by dlaliberte:

A closure is not only created when you return an inner function. In fact, the enclosing function does not need to return at all. You might instead assign your inner function to a variable in an outer scope, or pass it as an argument to another function where it could be used immediately. Therefore, the closure of the enclosing function probably already exists at the time that enclosing function was called since any inner function has access to it as soon as it is called.

var i;  function foo(x) {      var tmp = 3;      i = function (y) {          alert(x + y + (++tmp));      }  }  foo(2);  i(3);  

Answer by Chris S for How do JavaScript closures work?


Can you explain closures to a 5 year old?*

I still think Google's explanation works very well and is concise:

/*  *    When a function is defined in another function and it  *    has access to the outer function's context even after  *    the outer function returns.  *  * An important concept to learn in JavaScript.  */    function outerFunction(someNum) {      var someString = 'Hey!';      var content = document.getElementById('content');      function innerFunction() {          content.innerHTML = someNum + ': ' + someString;          content = null; // Internet Explorer memory leak for DOM reference      }      innerFunction();  }    outerFunction(1);?  

Proof that this example creates a closure even if the inner function doesn't return

*A C# question

Answer by Nathan Long for How do JavaScript closures work?


I wrote a blog post a while back explaining closures. Here's what I said about closures in terms of why you'd want one.

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.

In that sense, they let a function act a bit like an object with private attributes.

Full post:

So what are these closure thingys?

Answer by John Pick for How do JavaScript closures work?


JavaScript functions can access their:

  1. Arguments
  2. Locals (that is, their local variables and local functions)
  3. Environment, which includes:
    • globals, including the DOM
    • anything in outer functions

If a function accesses its environment, then the function is a closure.

Note that outer functions are not required, though they do offer benefits I don't discuss here. By accessing data in its environment, a closure keeps that data alive. In the subcase of outer/inner functions, an outer function can create local data and eventually exit, and yet, if any inner function(s) survive after the outer function exits, then the inner function(s) keep the outer function's local data alive.

Example of a closure that uses the global environment:

Imagine that the Stack Overflow Vote-Up and Vote-Down button events are implemented as closures, voteUp_click and voteDown_click, that have access to external variables isVotedUp and isVotedDown, which are defined globally. (For simplicity's sake, I am referring to StackOverflow's Question Vote buttons, not the array of Answer Vote buttons.)

When the user clicks the VoteUp button, the voteUp_click function checks whether isVotedDown == true to determine whether to vote up or merely cancel a down vote. Function voteUp_click is a closure because it is accessing its environment.

var isVotedUp = false;  var isVotedDown = false;    function voteUp_click()  {    if (isVotedUp)      return;    else if (isVotedDown)      SetDownVote(false);    else      SetUpVote(true);  }    function voteDown_click()  {    if (isVotedDown)      return;    else if (isVotedUp)      SetUpVote(false);    else      SetDownVote(true);  }    function SetUpVote(status)  {    isVotedUp = status;    // Do some CSS stuff to Vote-Up button  }    function SetDownVote(status)  {    isVotedDown = status;    // Do some CSS stuff to Vote-Down button  }  

All four of these functions are closures as they all access their environment.

Answer by Jacob Swartwood for How do JavaScript closures work?


I'm a big fan of analogy and metaphor when explaining difficult concepts, so let me try my hand with a story.

Once upon a time:

There was a princess...

function princess() {  

She lived in a wonderful world full of adventures. She met her Prince Charming, rode around her world on a unicorn, battled dragons, encountered talking animals, and many other fantastical things.

    var adventures = [];        function princeCharming() { /* ... */ }        var unicorn = { /* ... */ },          dragons = [ /* ... */ ],          squirrel = "Hello!";  

But she would always have to return back to her dull world of chores and grown-ups.

    return {  

And she would often tell them of her latest amazing adventure as a princess.

        story: function() {              return adventures[adventures.length - 1];          }      };  }  

But all they would see is a little girl...

var littleGirl = princess();  

...telling stories about magic and fantasy.

littleGirl.story();  

And even though the grown-ups knew of real princesses, they would never believe in the unicorns or dragons because they could never see them. The grown-ups said that they only existed inside the little girl's imagination.

But we know the real truth; that the little girl with the princess inside...

...is really a princess with a little girl inside.

Answer by StewShack for How do JavaScript closures work?


You're having a sleep over and you invite Dan. You tell Dan to bring one XBox controller.

Dan invites Paul. Dan asks Paul to bring one controller. How many controllers were brought to the party?

function sleepOver(howManyControllersToBring) {        var numberOfDansControllers = howManyControllersToBring;        return function danInvitedPaul(numberOfPaulsControllers) {          var totalControllers = numberOfDansControllers + numberOfPaulsControllers;          return totalControllers;      }  }    var howManyControllersToBring = 1;    var inviteDan = sleepOver(howManyControllersToBring);    // The only reason Paul was invited is because Dan was invited.   // So we set Paul's invitation = Dan's invitation.    var danInvitedPaul = inviteDan(howManyControllersToBring);    alert("There were " + danInvitedPaul + " controllers brought to the party.");  

Answer by Nathan Whitehead for How do JavaScript closures work?


I put together an interactive JavaScript tutorial to explain how closures work. What's a Closure?

Here's one of the examples:

var create = function (x) {      var f = function () {          return x; // We can refer to x here!      };      return f;  };  // 'create' takes one argument, creates a function    var g = create(42);  // g is a function that takes no arguments now    var y = g();  // y is 42 here  

Answer by mykhal for How do JavaScript closures work?


Wikipedia on closures:

In computer science, a closure is a function together with a referencing environment for the nonlocal names (free variables) of that function.

Technically, in JavaScript, every function is a closure. It always has an access to variables defined in the surrounding scope.

Since scope-defining construction in JavaScript is a function, not a code block like in many other languages, what we usually mean by closure in JavaScript is a function working with nonlocal variables defined in already executed surrounding function.

Closures are often used for creating functions with some hidden private data (but it's not always the case).

var db = (function() {      // Create a hidden object, which will hold the data      // it's inaccessible from the outside.      var data = {};        // Make a function, which will provide some access to the data.      return function(key, val) {          if (val === undefined) { return data[key] } // Get          else { return data[key] = val } // Set      }      // We are calling the anonymous surrounding function,      // returning the above inner function, which is a closure.  })();    db('x')    // -> undefined  db('x', 1) // Set x to 1  db('x')    // -> 1  // It's impossible to access the data object itself.  // We are able to get or set individual it.  

ems

The example above is using an anonymous function, which was executed once. But it does not have to be. It can be named (e.g. mkdb) and executed later, generating a database function each time it is invoked. Every generated function will have its own hidden database object. Another usage example of closures is when we don't return a function, but an object containing multiple functions for different purposes, each of those function having access to the same data.

Answer by dlaliberte for How do JavaScript closures work?


Taking the question seriously, we should find out what a typical 6-year-old is capable of cognitively, though admittedly, one who is interested in JavaScript is not so typical.

On Childhood Development: 5 to 7 Years it says:

Your child will be able to follow two-step directions. For example, if you say to your child, "Go to the kitchen and get me a trash bag" they will be able to remember that direction.

We can use this example to explain closures, as follows:

The kitchen is a closure that has a local variable, called trashBags. There is a function inside the kitchen called getTrashBag that gets one trash bag and returns it.

We can code this in JavaScript like this:

function makeKitchen () {    var trashBags = ['A', 'B', 'C']; // only 3 at first      return {      getTrashBag: function() {        return trashBags.pop();      }    };  }    var kitchen = makeKitchen();    kitchen.getTrashBag(); // returns trash bag C  kitchen.getTrashBag(); // returns trash bag B  kitchen.getTrashBag(); // returns trash bag A  

Further points that explain why closures are interesting:

  • Each time makeKitchen() is called, a new closure is created with its own separate trashBags.
  • The trashBags variable is local to the inside of each kitchen and is not accessible outside, but the inner function on the getTrashBag property does have access to it.
  • Every function call creates a closure, but there would be no need to keep the closure around unless an inner function, which has access to the inside of the closure, can be called from outside the closure. Returning the object with the getTrashBag function does that here.

Answer by Gerardo Lima for How do JavaScript closures work?


I know there are plenty of solutions already, but I guess that this small and simple script can be useful to demonstrate the concept:

// makeSequencer will return a "sequencer" function  var makeSequencer = function() {      var _count = 0; // Not accessible outside this function      var sequencer = function () {          return _count++;      }      return sequencer;  }    var fnext = makeSequencer();  var v0 = fnext();     // v0 = 0;  var v1 = fnext();     // v1 = 1;  var vz = fnext._count // vz = undefined  

Answer by goonerify for How do JavaScript closures work?


After a function is invoked, it goes out of scope. If that function contains something like a callback function, then that callback function is still in scope. If the callback function references some local variable in the immediate environment of the parent function, then naturally you'd expect that variable to be inaccesible to the callback function and return undefined.

Closures ensure that any property that is referenced by the callback function is available for use by that function, even when it's parent function may have gone out of scope

Answer by JVerstry for How do JavaScript closures work?


From a personal blog post:

By default, JavaScript knows two types of scopes: global and local.

var a = 1;    function b(x) {      var c = 2;      return x * c;  }  

In the above code, variable a and function b are available from anywhere in the code (that is, globally). Variable c is only available within the b function scope (that is, local). Most software developers won't be happy with this lack of scope flexibility, especially in large programs.

JavaScript closures help solving that issue by tying a function with a context:

function a(x) {      return function b(y) {          return x + y;      }  }  

Here, function a returns a function called b. Since b is defined within a, it automatically has access to whatever is defined in a, that is, x in this example. This is why b can return x + y without declaring x.

var c = a(3);  

Variable c is assigned the result of a call to a with parameter 3. That is, an instance of function b where x = 3. In other words, c is now a function equivalent to:

var c = function b(y) {      return 3 + y;  }  

Function b remembers that x = 3 in its context. Therefore:

var d = c(4);  

will assign the value 3 + 4 to d, that is 7.

Remark: If someone modifies the value of x (say x = 22) after the instance of function b has been created, this will be reflected in b too. Hence a later call to c(4) would return 22 + 4, that is 26.

Closures can also be used to limit the scope of variables and methods declared globally:

(function () {      var f = "Some message";      alert(f);  })();  

The above is a closure where the function has no name, no argument and is called immediately. The highlighted code, which declares a global variable f, limits the scopes of f to the closure.

Now, there is a common JavaScript caveat where closures can help:

var a = new Array();    for (var i=0; i<2; i++) {      a[i]= function(x) { return x + i ; }  }  

From the above, most would assume that array a would be initialized as follows:

a[0] = function (x) { return x + 0 ; }  a[1] = function (x) { return x + 1 ; }  a[2] = function (x) { return x + 2 ; }  

In reality, this is how a is initialized, since the last value of i in the context is 2:

a[0] = function (x) { return x + 2 ; }  a[1] = function (x) { return x + 2 ; }  a[2] = function (x) { return x + 2 ; }  

The solution is:

var a = new Array();    for (var i=0; i<2; i++) {      a[i]= function(tmp) {          return function (x) { return x + tmp ; }      } (i);  }  

The argument/variable tmp holds a local copy of the changing value of i when creating function instances.

Answer by srgstm for How do JavaScript closures work?


A function in JavaScript is not just a reference to a set of instructions (as in C language) but also includes a hidden data structure which is composed of references to all nonlocal variables it uses. Such two-piece functions are called closures. Every function in JavaScript can be considered a closure.

Closures are functions with a state. It is somewhat similar to "this" in the sense that "this" also provides state for a function but function and "this" are separate objects ("this" is just a fancy parameter, and the only way to bind it to a function is to create a closure). While "this" and function always live separately, a function cannot be separated from its closure.

Because all these external variables referenced by a lexically nested function are actually local variables in the chain of its lexically enclosing functions (global variables can be assumed to be local variables of some root function), and every single execution of a function creates new instances of its local variables, - every execution of a function returning (or otherwise transferring it out, such as registering it as a callback) a nested function creates a new closure (with its own potentially unique set of referenced nonlocal variables which represent its execution context).

Also, it must be understood that local variables in JavaScript are created not on the stack frame but in the heap and destroyed only when no one is referencing them. When a function returns, references to its local variables are decremented but can still be non-null if during the current execution they became part of a closure and are still referenced by its (lexically) nested functions (which can happen only if the references to these nested functions were returned or otherwise transferred to some external code).

An example:

function foo (initValue) {     //This variable is not destroyed when the foo function exits.     //It is 'captured' by the two nested functions returned below.     var value = initValue;        //Note that the two returned functions are created right now.     //If the foo function is called again, it will return      //new functions referencing a different 'value' variable.     return {         getValue: function () { return value; },         setValue: function (newValue) { value = newValue; }     }  }    function bar () {      //foo sets its local variable 'value' to 5 and returns an object with      //two functions still referencing that local variable      var obj = foo(5);        //extracting functions just to show that no 'this' is involved here      var getValue = obj.getValue;      var setValue = obj.setValue;        alert(getValue()); //displays 5      setValue(10);      alert(getValue()); //displays 10        //At this point getValue and setValue functions are destroyed       //(in reality they are destroyed at the next iteration of the garbage collector).      //The local variable 'value' in the foo is no longer referenced by       //anything and is destroyed too.  }    bar();  

Answer by ketan for How do JavaScript closures work?


Closures are a means through which inner functions can refer to the variables present in their outer enclosing function after their parent functions have already terminated.

// A function that generates a new function for adding numbers.  function addGenerator( num ) {      // Return a simple function for adding two numbers      // with the first number borrowed from the generator      return function( toAdd ) {          return num + toAdd      };  }    // addFive now contains a function that takes one argument,  // adds five to it, and returns the resulting number.  var addFive = addGenerator( 5 );  // We can see here that the result of the addFive function is 9,  // when passed an argument of 4.  alert( addFive( 4 ) == 9 );  

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.