Javascript constructor function to count the number of instances

3.8k Views Asked by At

Okay, so I want to create a constructor function in javascript which will count the total number of instances which are created using this constructor.

var Component = function(name) {
    this.name = name;
    this.add = function(){this.prototype.countInstances++;};
    this.add();
};

and

Component.prototype.countInstances=0;

As I understand it correctly, the countInstances variable is added to the prototype and will act like a static copy for all the instances and will act as my counter.

The problem with this code is that since I'm declaring the countInstances after the constructor, I'm getting an error in the constructor code itself. How to correct this??

4

There are 4 best solutions below

0
On BEST ANSWER

As I understand it correctly, the countInstances variable is added to the prototype and will act like a static copy for all the instances and will act as my counter.

No, it will be, in effect, a default value for instances, not a "static." If you put it on Component.prototype, all instances will inherit it via the prototype chain, but changing it via an instance will give that instance its own copy of it. Example:

var Foo = function() {
};
Foo.prototype.bar = 0;
var f1 = new Foo();
var f2 = new Foo();
console.log(f1.bar, f2.bar); // 0, 0 -- both are still using the `bar` on the prototype
++f1.bar;
console.log(f1.bar, f2.bar); // 1, 0 -- f1 now has its own
Foo.prototype.bar += 2;
console.log(f1.bar, f2.bar); // 1, 2 -- f2 is still using the `bar` on the prototype

The problem with this code is that since I'm declaring the countInstances after the constructor, I'm getting an error in the constructor code itself. How to correct this??

No, the problem is that your instances have no this.prototype object. The prototype property on the function is not copied as a prototype property on instances; it's assigned to them as their prototype, which (somewhat confusingly) isn't called prototype. For a long time it didn't have a name outside the spec at all. You can access it via Object.getPrototypeOf(this) or (this will be standard for browser-based JavaScript as of the next spec) the __proto__ property.

But putting it on the prototype probably doesn't make sense. I'd just use a property on the function itself:

var Component = function(name) {
    this.name = name;
    this.add = function(){Component.instances++;};
    this.add();
};
Component.instances = 0;

But you said you wanted to count the number of objects created by the constructor; the above counts the number of times the add method is called. To count the number of instances created by the constructor, increment it in the constructor:

var Component = function(name) {
    Component.instances++;
    this.name = name;
    this.add = function(){/*Presumably you're doing something here*/};
    this.add();
};
Component.instances = 0;
0
On
var ComponentCounter = 0;

var Component = function(name) {
    this.name = name;
    this.add = function(){this.prototype.countInstances++;};
    this.add();
    ComponentCounter++;
    // or Component.counter++;
};

// or add it as a property of Component after it has been defined
// Component.counter = 0;

Variables in the prototype belong to the instance so you have to keep track of that data on a variable that is persisted between instances.

0
On

If you'd like a property to be attached to the class itself, and not instances of the class, you don't want to add the property to prototype:

var Component = function(name) {
  this.name = name;
  Component.instanceCount++;
};

Component.instanceCount = 0;

This way, you're assigning each name to its instance, and the total instance count to the static class:

var foo = new Component('bar');
var baz = new Component('qux');

console.info(foo.name, baz.name, Component.instanceCount);

>> 'bar', 'qux', 2
0
On

We will be able to do the same by using:

function component() {
    if(component.prototype.counter) {    component.prototype.counter = 0; }
    component.prototype.counter++;
    this.add = function(){ /*... do something here....*/ }
}

By initiating counter inside the function body, we will be able to keep the count (number of times function called).