Furhan S.
Furhan S.

Reputation: 1524

Declaring private static member variable in JavaScript

I am stuck with a design pattern in JavaScript where I would like to create a private static member variable for keeping object count. Something along these lines:

var person = function(name){
    //How to persist this value across multiple calls avoiding Globals
    var _personCount = _personCount || 0;
    _personCount++;
    var _name = name;
    getPerson = function(){
          return "Person is: " + _name;
    }
};

person("foo");//_personCount should be 1 after this call
person("bar");//_personCount should be 2 after this call

The idea is something to similar to private static variables, accessible only to the class's internal variables

Upvotes: 1

Views: 268

Answers (4)

rajuGT
rajuGT

Reputation: 6404

You must create the private static variable in the closure context.

var person = (function() {
    //private variable
    var _personCount = 1;

    return function(name) {
        this.name = name;
        this.id = _personCount++;
    }

}());

var foo = new person('foo');
console.log(foo.id + ' ' + foo.name);//1 foo

var boo = new person('boo');
console.log(boo.id + ' ' + boo.name);//2 boo

Here the enclosing anonymous function can never be called again. It gets executed while JS engine parses your code, and creates _personCount variable which can be accessed only by inner function function(name) making it like private static.

Upvotes: 2

Hitmands
Hitmands

Reputation: 14159

I think that this could help you! note: the prototype property for having instance method! note: count, instead, is static!

var Person = (function() {
  var counter = 0;
  function Person(name) {
    this.name = name;
  }
  
  Person.prototype.getName = function() {
    counter += 1;
    return this.name;
  };

  Person.count = function() { return counter; };
return Person;
})();

var superman = new Person('SuperMan');
var batman = new Person('BatMan');

var el = function() { return window.document.getElementById('counter'); }
function p1() {
  var name = superman.getName();
  el().innerText = name + ' - ' + Person.count();
}
function p2() {
  var name = batman.getName();
  el().innerText = name + ' - ' + Person.count();
}
<h1 id="counter">0</h1>

<button onclick="p1()">Person1</button>
<button onclick="p2()">Person2</button>

Upvotes: 1

Josh Beam
Josh Beam

Reputation: 19772

You can use the revealing module pattern:

var something = (function() {
  var myThing = 0;

  return {
    doSomething: function() {
      myThing++;
    }
  };
})();

something.doSomething(); // myThing is now 1

The variable is within what's called an IIFE (immediately invoked function expression) will remain throughout the lifecycle of the program.

If you're going to instantiate the module more than once in different places, you'll need to also create a singleton.

Upvotes: 5

Barmar
Barmar

Reputation: 780724

If you want the variable to be global to all the persons, you need to define them within the scope of a containing function. This can be an IIFE, since it only need to run once.

var person = (function() {
    var _personCount = _perconCount || 0;
    return function(name) {
        _personCount++;
        var _name = name;
        getPerson = function() {
            return "Person is: " + _name;
        };
    };
})();

Upvotes: 2

Related Questions