Modify all class members using an instance method

In JavaScript, is it possible to call an instance method on an object that affects all its brothers?

For example, let's say I have the following class:

function Thing() { this.active = false; } Thing.prototype = { constructor: Thing, activate: function() { this.active = true; }, deactivate: function() { this.active = false; } }; 

Is it possible to create an activateAll method that can activate all instances of the Thing class?

I need this.active as an instance variable.

+8
javascript prototype
source share
2 answers

You can save all instances in an array and iterate over them to change their active property. However, storing all instances means that they will not collect garbage, so you will waste memory. And if the array becomes huge, repeating it will be slow.

 var Thing = (function() { // Use a closure to hide `instances` var instances = []; function Thing() { this.active = false; instances.push(this); } Thing.prototype.activate = function() { this.active = true; }; Thing.prototype.activateAll = function() { instances.forEach(function(instance) { instance.active = true; }); }; return Thing; })(); 

The best way would be to determine the overall default activity and default priority, as well as your own action and own priority for each instance. Then,

  • To get instance activity, compare the default priority and your own priority. The biggest decision is whether to return the default action or its own action.
  • To set instance activity, update your own activity. If the default activity is greater, increase your own priority.
  • To establish the activity of all instances, update the default action and increase the default priority.
 var Thing = (function() { var defActive = false, /* default activity */ defPriority = 0; /* default priority */ /* `defPriority >= ownPriority` will always hold */ function Thing() { var ownActive, ownPriority = -1; Object.defineProperty(this, 'active', { get: function() { return defPriority > ownPriority ? defActive : ownActive; }, set: function(val) { ownActive = val; ownPriority = defPriority; } }); } Thing.prototype.activate = function() { this.active = true; }; Thing.prototype.activateAll = function() { defActive = true; ++defPriority; }; return Thing; })(); 

If activateAll will be called many times, and you do not want to increase defPriority , you can add a boolean to find out if some native property has reached its default.

 var Thing = (function() { var defActive = false, /* default activity */ defPriority = 0, /* default priority */ someOwnPriorityReachedDefPriority = false; function Thing() { var ownActive, ownPriority = -1; Object.defineProperty(this, 'active', { get: function() { return defPriority > ownPriority ? defActive : ownActive; }, set: function(val) { ownActive = val; ownPriority = defPriority; someOwnPriorityReachedDefPriority = true; } }); } Thing.prototype.activate = function() { this.active = true; }; Thing.prototype.activateAll = function() { defActive = true; if(someOwnPriorityReachedDefPriority) { ++defPriority; someOwnPriorityReachedDefPriority = false; } }; return Thing; })(); 

In any case, note that adding this method to the prototype does not make much sense. According to the principles of OOP, a method call in a variable should not affect other variables. Instead, consider adding a method to the constructor itself.

A complete example might be:

 var Thing = (function() { var defActive = false, /* default activity */ defPriority = 0, /* default priority */ someOwnPriorityReachedDefPriority = false; function Thing() { var ownActive, ownPriority = -1; Object.defineProperty(this, 'active', { get: function() { return defPriority > ownPriority ? defActive : ownActive; }, set: function(val) { ownActive = val; ownPriority = defPriority; someOwnPriorityReachedDefPriority = true; } }); } Thing.prototype.activate = function() { this.active = true; }; Thing.prototype.deactivate = function() { this.active = false; }; Object.defineProperty(Thing, 'activeAll', { set: function(val) { defActive = val; if(someOwnPriorityReachedDefPriority) { ++defPriority; someOwnPriorityReachedDefPriority = false; } } }); Thing.activateAll = function() { Thing.activeAll = true; }; Thing.deactivateAll = function() { Thing.activeAll = false; }; return Thing; })(); 
+8
source share

You need an instances array, for example:

 var instances = []; 

Change Thing as follows:

 function Thing() { this.active = false; instances[instances.length] = this; } 

Implement methods by iteration:

 function activateAll() { for (var index in instances) { instances[index].active = true; } } 

You can generalize this, for example:

 function genericOperation(f, p) { for (var index in instances) { instances[index].f(p); } } 
+1
source share

All Articles