1

I was reading Closures and it has the example of the following closure.

var makeCounter = function() {
var privateCounter = 0;
  function changeBy(val) 
     {
       privateCounter += val;
     }
  return 
     {
       increment: function() 
     {
       changeBy(1);
     },
  decrement: function() 
     {
       changeBy(-1);
     },
  value: function() 
     {
       return privateCounter;
     }
   }
};

var counter1 = makeCounter();
var counter2 = makeCounter();
alert(counter1.value()); /* Alerts 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* Alerts 2 */
counter1.decrement();
alert(counter1.value()); /* Alerts 1 */
alert(counter2.value()); /* Alerts 0 */

I was wondering what the difference and advantages/disadvantages are between this closure and the following code that produce the same results.

var makeCounter = function() {
var privateCounter = 0;
  function changeBy(val) 
      {
        privateCounter += val;
      };
   this.increment= function() 
     {
       changeBy(1);
     };
   this.decrement= function()
     {
       changeBy(-1);
     };
   this.value= function() 
     {
       return privateCounter;
     };
  };

var counter1 = new makeCounter();
var counter2 = new makeCounter();
alert(counter1.value()); /* Alerts 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* Alerts 2 */
counter1.decrement();
alert(counter1.value()); /* Alerts 1 */
alert(counter2.value()); /* Alerts 0 */
Sevle
  • 3,109
  • 2
  • 19
  • 31
943A
  • 166
  • 8
  • Select your code, hit the `{}` button in the toolbar to **indent it by 4 spaces**. That's how you mark code as code here. Read the rest of the editing help while you're at it. It'd do it for you, but I'm not going to clean all those
    s out.
    – deceze Apr 09 '15 at 13:02

1 Answers1

1

Your second version does use closures as well, there's hardly a difference in that regard.

The important difference is that your first makeCounter is a factory that returns an object literal (which inherits from Object.prototype), while your second makeCounter is a constructor function (needs to be called with new) that does return an instance which inherits from makeCounter.prototype. You could gain some advantages by moving your methods on the prototype:

function Counter() {
    var privateCounter = 0;
    this.changeBy = function changeBy(val) {
        privateCounter += val;
    };
    this.value = function() {
        return privateCounter;
    };
}
Counter.prototype.increment = function() {
    this.changeBy(1);
};
Counter.prototype.decrement = function() {
    this.changeBy(-1);
};

You could avoid the closures (privileged methods) and use prototype methods only:

function Counter() {
    this.counter = 0; // no more private
}
Counter.prototype.valueOf = function() {
    return this.ounter;
};
Counter.prototype.increment = function() {
    this.counter += 1;
};
Counter.prototype.decrement = function() {
    this.counter -= 1;
};
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375