1

I am trying to understand closure, and playing with the following code.I am expecting the value of i to be same across all the objects,as closure keeps a reference to the variable of outer function.

 function Test(){
 var i=10;
 return{
   get:function(){return i;},
   inc:function(){i++;}
   }
 }
var test1= Test();
var test2=Test();
test1.get(); //outputs 10
test1.inc();
test2.get(); //outputs 10, I am expecting it to be 11

Is my understanding of closures correct, Am I even creating a closure in this case? I am new to closures, a detailed explanation would be great. Thanks.

Nirbhay Jha
  • 491
  • 5
  • 13
  • 3
    you have created 2 closures. I think what you are looking for is a singleton implementation of the function Test. http://stackoverflow.com/questions/1479319/simplest-cleanest-way-to-implement-singleton-in-javascript this maybe helpful – Himanshu Tanwar Aug 29 '16 at 06:56
  • 2
    Each time you call `Test()` you get a new closure. – nnnnnn Aug 29 '16 at 07:00
  • 2
    Why do you say "with no inner function"? There **is** an inner function, actually two of them, `get` and `incr`, both of which close over `i`. –  Aug 29 '16 at 08:26
  • Changed the title of the question. – Nirbhay Jha Aug 29 '16 at 10:25

2 Answers2

2

As others have mentioned, you've basically created two closures.

The easiest way to understand closures is that it is a generalisation of the concept of global variables. In fact, global variables in javascript is nothing more than a closure in global scope.

A closure is the mechanism by which the body of a function may reference variables in outer scope. As I said above, global variables are nothing more than a closure:

var x;

function x_plus_plus () {
    x++; // this variable is captured by a closure
}

Every scope allows you to create a closure. So apart from the global scope you can also create a closure inside other functions. To me, personally, the minimum example code that best illustrates what closures are is an IIFE that defines two functions that share a variable:

var incr;
var val;

(function(){
    var x = 0; // shared with the functions below var via closure

    incr = function(){x++};
    val = function(){return x};
})();

incr();
incr();
console.log(val()); // outputs 2 because the functions share x

console.log(x); // syntax error - x does not exist in this scope

Note that a closure is what happens between a variable and functions declared in that variable's scope. It is not what happens between a variable and the function the variable is declare in:

function () {  <─────┐
                     ├── this is not a closure
    var foo; <───────┘
}

function () {
    var foo;   <────────────────┐
                                ├── this is a closure
    function bar () {           │
        do_something(foo);  <───┘
    }
}

var x;   <───────────────┐
                         ├── this is also a closure but we
function y () {          │   normally call it "global variable" 
    do_something(x); <───┘
}

Side note: Global variables in js are actually a bit unique because they're also properties of the global (window) object. But in theory they behave as if they're an instance of a closure. The point is that thinking of closures as a global-variable-like mechanism is the easiest way to understand them.

slebetman
  • 109,858
  • 19
  • 140
  • 171
  • Thanks! A side question,Is it mandatory to have at least one function inside another to have a closure ? – Nirbhay Jha Aug 29 '16 at 10:31
  • @NirbhayJha: Not really but then that would just be a global variable then. If it's not linked to the outer scope (see the "not a closure" example above) then it's just a local variable. – slebetman Aug 29 '16 at 12:11
0

You have created 2 different instances. So that 2 different memory has been allocated, that means 2 different closures. Don't confuse by thinking that memory has been shared across the instances when it comes to closure.

test1.get(); //10
test1.inc();
test1.get(); //11
test2.get(); //10

If you want to create a shared variable, then read about prototypes. Since prototype is a live connection to a function reference.

Rajaprabhu Aravindasamy
  • 66,513
  • 17
  • 101
  • 130
  • Prototypes do not work how you apparently think they do. They do not serve as a way to have shared read/write variables. The first time you set (assign to) the property, it will create an instance-specific version of that property. –  Aug 29 '16 at 08:24