Say I have this code:
function ParentClass()
{
var anArray = [ ];
this.addToArray = function(what)
{
anArray.push(what);
console.log(anArray);
};
}
FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;
function FirstSubClass()
{
this.addToArray('FirstSubClass');
}
SecondSubClass.prototype = new ParentClass();
SecondSubClass.prototype.constructor = SecondSubClass;
function SecondSubClass()
{
this.addToArray('SecondSubClass');
}
When I run new FirstSubClass() I see a single value array in the console. And when I run new SecondSubClass(), again, I see a single value array.
However, why is it when I run them again (i.e. new FirstSubClass(); new SecondSubClass();) I then see the arrays added to rather than new ones being created?
The rationale here is that I'm creating new instances of a class, therefore why are they sharing the same private property?
How can I avoid this so when I do, for e.g., new FirstSubClass() I then see a single value array no matter how many times I create a new instance of the class?
Keep in mind that you've only called new ParentClass() once for each subclass. That means that the private array variable is part of the prototype object for those subclasses. There's only one prototype object, so there's only one array (per subclass).
Each call to new FirstSubClass() generates a new instance that shares the same prototype object. The call to addToArray() therefore adds an element to that same array that was created when the prototype object was created.
edit — if you want per-instance arrays, you'd have to do something like this:
function ParentClass() {
this.addToArray = function(value) { this.instanceArray.push(value); };
};
function FirstSubClass() {
this.instanceArray = [];
this.addToArray("First");
}
FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;
First, sub-classing in JS is typically a bad idea, because people think that they're getting extension, where every instance has its own copy of properties and methods...
...really, they're getting public static access to the parent's stuff.
Even better, that public static stuff has no access to the encapsulated variables, so there's really no manipulation of private data, unless you're using private functions (with a public interface) to pass data to and collect return values from, the public static stuff.
var Parent = function () {
this.static_prop = 0;
this.static_method = function (num) { this.static_prop += 1; return num + this.static_prop; };
};
var Child = function (num) {
this.public_func = function () { num = this.static_method(num); };
};
Child.prototype = new Parent();
var child = new Child(13);
child.public_func();
Just calling this.static_method wouldn't help, because it would have 0 access to num, which means that you're wrapping things which you inherited to grant them access to use private data as inputs, which means that you're doing most of the writing you'd be doing anyway, regardless of inheritance, because your expectations of .prototype were backwards.
Might I suggest Dependency Injection, instead?
Component-based programs?
var Iterator = function () {
var count = 0,
min = 0,
max = 0,
reset = function () { count = min; },
next = function () { count = count >= max ? min : count; return count += 1; },
set_min = function (val) { min = val; },
set_max = function (val) { max = val; },
public_interface = { reset : reset, count : count, set_min : set_min, set_max : set_max };
return public_interface;
},
Thing = function (iter) {
var arr = [],
currentObj = null,
nextObj = function () {
currentObj = arr[iter.next()];
},
add = function (obj) {
arr.push(obj); iter.set_max(arr.length);
},
public_interface = { next : nextObj, add : add };
return public_interface;
};
var thing = Thing(Iterator());
thing.add({});
thing.next();
It's a convoluted example, but now every instance is going to be given exactly what it needs to do its job (because the constructor requires it -- or you can add the dependency later, through a public method, or as a public-property).
The interfaces for each module can now also get as simple and as clean as you'd like, as you don't have to wrap unexpected static-helpers to get private data...
Now you know what's private, you know what you're extending to the public, and you have clean ins and outs wherever you want to put them.
You are only constructing a new instance of ParentClass once per subclass and that is to apply it to your prototype. If you want each instance to have its own copy of the private array and its own copy of the function "addToArray" you will need to invoke the ParentClass constructor function within your other objects constructors:
function ParentClass(){
var anArray = [ ];
this.addToArray = function(what){
anArray.push(what);
console.log(anArray);
};
}
FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;
function FirstSubClass(){
//call the parents constructor where "this" points to your FirstSubClass instance
ParentClass.call( this );
this.addToArray('FirstSubClass');
}
SecondSubClass.prototype = new ParentClass();
SecondSubClass.prototype.constructor = SecondSubClass;
function SecondSubClass(){
ParentClass.call( this );
this.addToArray('SecondSubClass');
}
try this:
http://jsfiddle.net/3z5AX/2/
function ParentClass()
{
var anArray = [ ];
this.addToArray = function(what)
{
anArray.push(what);
document.getElementById("i").value = anArray;
};
}
//FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;
function FirstSubClass()
{
this.parent = new ParentClass()
this.parent.addToArray('FirstSubClass');
}
var q = new FirstSubClass();
var r = new FirstSubClass();
All Subclasses share the same parent class, thus the same private anArray
The solution is to use the Mixin pattern.
// I have the habbit of starting a mixin with $
var $AddToArray = function(obj) {
var array = [];
obj.addToArray = function(what) {
array.push(what);
console.log(array);
};
}
var FirstClass = function() {
$AddToArray(this);
}
var SecondClass = function() {
$AddToArray(this);
}
Related
I think I've misunderstood something about OOP in JavaScript. As I understand it, the point of setting up a private variable with its own getter and setter functions is to protect it from accidental alteration elsewhere in the program. But I'm finding it very easy to accidentally change private variables using their getter functions, which means I must be doing something wrong.
function Phone(os) {
this.os = os;
var _phoneBook = []; // phoneBook is intended to be private
this.newNumber = function(phoneNumber) { // set new number
_phoneBook.push(phoneNumber);
}
this.listNumbers = function() { // get all numbers
return _phoneBook;
}
}
var andy = new Phone("Android");
andy.newNumber("555-123-4567");
console.log(andy.listNumbers()); // => ["555-123-4567"]
// You shouldn't be able to set a private property through a getter function, but you can.
var extendedPhoneBook = andy.listNumbers().push("123-456-7890");
console.log(andy.listNumbers()); // => ["555-123-4567", "123-456-7890"]
That Array is being passed as a reference, so when calling listNumbers() you are returning the Actual Array to the exterior. You can return copies of the Array with something like this:
function Phone(os) {
this.os = os;
var _phoneBook = []; // phoneBook is intended to be private
this.newNumber = function(phoneNumber) { // set new number
_phoneBook.push(phoneNumber);
}
this.listNumbers = function() { // get all numbers
return _phoneBook.slice(0);
}
}
you might consider changing function listNumbers to something like enumerateNumbers that takes a function that gets passed a string for each number in your list to hide the internal array, something like this:
function Phone(os) {
this.os = os;
var _phoneBook = []; // phoneBook is intended to be private
this.newNumber = function(phoneNumber) { // set new number
_phoneBook.push(phoneNumber);
}
this.enumerateNumbers = function(cb) { // get all numbers
for (var idx in _phoneBook) {
cb(_phoneBook[idx]);
}
}
}
var andy = new Phone("Android");
andy.newNumber("555-123-4567");
andy.enumerateNumbers(function(num) { console.log(num); })
Out the following two ways, which format for defining object is good considering performance and usage:
//Object created with public members defined using this.
var object1 = function () {
var private_i = null;
this.public_j = null;
//public function
this.public_func = function () {
}
}
OR
//Object created with public members defined using return patterns.
var object2 = function () {
var private_i = null,
public_j = null,
//private function will be exposed from return statement.
_public_func = function () {
};
return {
public_func : _public_func
};
}
The difference between the two relates to inheritance and usage. Your object2 always creates objects directly backed by Object.prototype and doesn't require use of the new keyword; your object1 creates object backed by object1.prototype (which is in turn backed by Object.prototype) and does require use of new.
Neither is really "better" in any objective way, they are just two different ways of using JavaScript, which will have fundamentally the same performance. The first one is much more common, the second one is advocated by a small but vocal minority within the JavaScript community.
The object1 example is more typically written like this:
function Object1() {
var private_i = null;
this.public_j = null;
//public function
this.public_func = function () {
};
}
Note that the first letter in such functions is capitalized (by overwhelming convention).
The prototype thing comes into it if you're going to have functions that don't need access to private_i: You could put those on the object that will be assigned to new objects created via new Object1 like so:
function Object1() {
var private_i = null;
this.public_j = null;
//public function
this.public_func = function () {
};
}
Object1.prototype.someOtherFunction = function() {
// Doesn't use `private_i`
};
You can also use prototypes with your object2, like so:
//Object created with public members defined using return patterns.
var object2Prototype = {
someOtherFunction: function() {
// Doesn't need private_i
};
};
var object2 = function () {
var private_i = null,
public_j = null,
//private function will be exposed from return statement.
_public_func = function () {
};
var obj = Object.create(object2Prototype);
obj.public_func = _public_func;
return obj;
};
Background
I decided I would practice by making a simple calculator app in JS. The first step was to implement a stack class. I ran into some problems however in achieving data encapsulation with the revealing prototype pattern (?). Here's how it looks right now:
Stack "class":
var Stack = (function () {
var Stack = function() {
this.arr = []; // accessible to prototype methods but also to public
};
Stack.prototype = Object.prototype; // inherits from Object
Stack.prototype.push = function(x) {
this.arr.push(x);
};
Stack.prototype.pop = function() {
return this.arr.length ? (this.arr.splice(this.arr.length - 1, 1))[0] : null;
};
Stack.prototype.size = function() {
return this.arr.length;
};
Stack.prototype.empty = function() {
return this.arr.length === 0;
};
return Stack;
})();
Test code:
var s1 = new Stack();
var s2 = new Stack();
for(var j = 1, k = 2; j < 10, k < 11; j++, k++) {
s1.push(3*j);
s2.push(4*k);
}
console.log("s1:");
while(!s1.empty()) console.log(s1.pop());
console.log("s2:");
while(!s2.empty()) console.log(s2.pop());
The Problem
The only problem is that the arr is accessible. I would like to hide the arr variable somehow.
Attempts at a Solution
My first idea was to make it a private variable like Stack:
var Stack = (function () {
var arr = []; // private, but shared by all instances
var Stack = function() { };
Stack.prototype = Object.prototype;
Stack.prototype.push = function(x) {
arr.push(x);
};
// etc.
})();
But of course this approach doesn't work, because then the arr variable is shared by every instance. So it's a good way of making a private class variable, but not a private instance variable.
The second way I thought of (which is really crazy and definitely not good for readability) is to use a random number to restrict access to the array variable, almost like a password:
var Stack = (function() {
var pass = String(Math.floor(Math.pow(10, 15 * Math.random()));
var arrKey = "arr" + pass;
var Stack = function() {
this[arrKey] = []; // private instance and accessible to prototypes, but too dirty
};
Stack.prototype = Object.prototype;
Stack.prototype.push = function(x) {
this[arrKey].push(x);
};
// etc.
})();
This solution is... amusing. But obviously not what I want to do.
The last idea, which is what Crockford does, allows me to create a private instance member, but there's no way I can tell to make this visible to the public prototype methods I'm defining.
var Stack = (function() {
var Stack = function() {
var arr = []; // private instance member but not accessible to public methods
this.push = function(x) { arr.push(x); }; // see note [1]
}
})();
[1] This is almost there, but I don't want to have the function definitions within the var Stack = function() {...} because then they get recreated every time that an instance is created. A smart JS compiler will realize that they don't depend on any conditionals and cache the function code rather than recreating this.push over and over, but I'd rather not depend on speculative caching if I can avoid it.
The Question
Is there a way to create a private instance member which is accessible to the prototype methods? By somehow utilizing the 'bubble of influence' created by the enclosing anonymous function?
You could use a factory function that creates an instance for you:
function createStack() {
var arr = [];
function Stack() {
};
Stack.prototype = Object.prototype; // inherits from Object
Stack.prototype.push = function(x) {
arr.push(x);
};
Stack.prototype.pop = function() {
return arr.length ? (this.arr.splice(this.arr.length - 1, 1))[0] : null;
};
Stack.prototype.size = function() {
return arr.length;
};
Stack.prototype.empty = function() {
return arr.length === 0;
};
return new Stack();
}
You would be defining the class on every execution of the factory function, but you could get around this by changing this to define most of Stack outside the constructor function, like the parts that dont use arr could be further up the prototype chain. Personally I use Object.create instead of prototype now and I almost always use factory functions to make instances of these types of objects.
Another thing you could do is maintain a counter that keeps track of the instance and holds on to an array of arrays.
var Stack = (function() {
var data = [];
var Stack = function() {
this.id = data.length;
data[this.id] = [];
};
Stack.prototype = Object.prototype;
Stack.prototype.push = function(x) {
data[this.id].push(x);
};
// etc.
}());
Now you have the hidden data multi dimensional array, and every instance just maintains its index in that array. You have to be careful to manage the memory now though, so that when your instance isn't being used anymore you remove what's in that array. I don't recommend doing it this way unless you are disposing your data carefully.
The short answer here, is that you can't have all things, without sacrificing a little.
A Stack feels like a struct of some kind, or at very least, a data-type which should have either a form of peek or read-access, into the array.
Whether the array is extended or not, is of course up to you and your interpretation...
...but my point is that for low-level, simple things like this, your solution is one of two things:
function Stack () {
this.arr = [];
this.push = function (item) { this.arr.push(item); }
// etc
}
or
function Stack () {
var arr = [];
var stack = this;
extend(stack, {
_add : function (item) { arr.push(item); },
_read : function (i) { return arr[i || arr.length - 1]; },
_remove : function () { return arr.pop(); },
_clear : function () { arr = []; }
});
}
extend(Stack.prototype, {
push : function (item) { this._add(item); },
pop : function () { return this._remove(); }
// ...
});
extend here is just a simple function that you can write, to copy the key->val of objects, onto the first object (basically, so I don't have to keep typing this. or Class.prototype..
There are, of course, dozens of ways of writing these, which will all achieve basically the same thing, with modified styles.
And here's the rub; unless you do use a global registry, where each instance is given its own unique Symbol (or unique-id) at construction time, which it then uses to register an array... ...which of course, means that the key then needs to be publicly accessible (or have a public accessor -- same thing), you're either writing instance-based methods, instance-based accessors with prototyped methods, or you're putting everything you need in the public scope.
In the future, you will be able to do things like this:
var Stack = (function () {
var registry = new WeakMap();
function Stack () {
var stack = this,
arr = [];
registry[stack] = arr;
}
extend(Stack.prototype, {
push (item) { registry[this].push(item); }
pop () { return registry[this].pop(); }
});
return Stack;
}());
Nearly all bleeding-edge browsers support this, currently (minus the shorthand for methods).
But there are ES6 -> ES5 compilers out there (Traceur, for instance).
I don't think WeakMaps are supported in Traceur, as an ES5 implementation would require a lot of hoops, or a working Proxy, but a Map would work (assuming that you handled GC yourself).
This lends me to say that from a pragmatic standpoint, for a class as small as Stack you might as well just give each instance its own methods, if you really want to keep the array internal.
For other harmless, tiny, low-level classes, hiding data might be pointless, so all of it could be public.
For larger classes, or high-level classes, having accessors on instances with prototyped methods stays relatively clean; especially if you're using DI to feed in lower-level functionality, and the instance accessors are just bridging from the interface of the dependency, into the shape you need them to be, for your own interface.
A real solution
EDIT: It turns out this solution is basically the same as the one described here, first posted by HMR in a comment to my question above. So definitely not new, but it works well.
var Stack = (function Stack() {
var key = {};
var Stack = function() {
var privateInstanceVars = {arr: []};
this.getPrivateInstanceVars = function(k) {
return k === key ? privateInstanceVars : undefined;
};
};
Stack.prototype.push = function(el) {
var privates = this.getPrivateInstanceVars(key);
privates.arr.push(el);
};
Stack.prototype.pop = function() {
var privates = this.getPrivateInstanceVars(key);
return privates.arr.length ? privates.arr.splice(privates.arr.length - 1, 1)[0] : null;
};
Stack.prototype.empty = function() {
var privates = this.getPrivateInstanceVars(key);
return privates.arr.length === 0;
};
Stack.prototype.size = function() {
var privates = this.getPrivateInstanceVars(key);
return privates.arr.length;
};
Stack.prototype.toString = function() {
var privates = this.getPrivateInstanceVars(key);
return privates.arr.toString();
};
Stack.prototype.print = function() {
var privates = this.getPrivateInstanceVars(key);
console.log(privates.arr);
}
return Stack;
}());
// TEST
// works - they ARE separate now
var s1 = new Stack();
var s2 = new Stack();
s1.push("s1a");
s1.push("s1b");
s2.push("s2a");
s2.push("s2b");
s1.print(); // ["s1a", "s1b"]
s2.print(); // ["s2a", "s2b"]
// works!
Stack.prototype.push.call(s1, "s1c");
s1.print(); // ["s1a", "s1b", "s1c"]
// extending the Stack
var LimitedStack = function(maxSize) {
Stack.apply(this, arguments);
this.maxSize = maxSize;
}
LimitedStack.prototype = new Stack();
LimitedStack.prototype.constructor = LimitedStack;
LimitedStack.prototype.push = function() {
if(this.size() < this.maxSize) {
Stack.prototype.push.apply(this, arguments);
} else {
console.log("Maximum size of " + this.maxSize + " reached; cannot push.");
}
// note that the private variable arr is not directly accessible
// to extending prototypes
// this.getArr(key) // !! this will fail (key not defined)
};
var limstack = new LimitedStack(3);
limstack.push(1);
limstack.push(2);
limstack.push(3);
limstack.push(4); // Maximum size of 3 reached; cannot push
limstack.print(); // [1, 2, 3]
Cons: basically none, other than remembering a little extra code
Original solution
(The first method originally posted was substantially different from what is below, but through some careless editing I seem to have lost it. It didn't work as well anyway, so no real harm done.)
Here a new object/prototype is created with every instantiation, but it borrows much of the code from the static privilegedInstanceMethods. What still fails is the ability to do Stack.prototype.push.call(s1, val), but now that the prototype is being set on the object, I think we're getting closer.
var Stack = (function() {
var privilegedInstanceMethods = {
push: function(x) {
this.arr.push(x);
},
pop: function() {
return this.arr.length ? this.arr.splice(this.arr.length - 1, 1)[0] : null;
},
size: function() {
return this.arr.length;
},
empty: function() {
return this.arr.length === 0;
},
print: function() {
console.log(this.arr);
},
};
var Stack_1 = function() {
var Stack_2 = function() {
var privateInstanceMembers = {arr: []};
for (var k in privilegedInstanceMethods) {
if (privilegedInstanceMethods.hasOwnProperty(k)) {
// this essentially recreates the class each time an object is created,
// but without recreating the majority of the function code
Stack_2.prototype[k] = privilegedInstanceMethods[k].bind(privateInstanceMembers);
}
}
};
return new Stack_2(); // this is key
};
// give Stack.prototype access to the methods as well.
for(var k in privilegedInstanceMethods) {
if(privilegedInstanceMethods.hasOwnProperty(k)) {
Stack_1.prototype[k] = (function(k2) {
return function() {
this[k2].apply(this, arguments);
};
}(k)); // necessary to prevent k from being same in all
}
}
return Stack_1;
}());
Test:
// works - they ARE separate now
var s1 = new Stack();
var s2 = new Stack();
s1.push("s1a");
s1.push("s1b");
s2.push("s2a");
s2.push("s2b");
s1.print(); // ["s1a", "s1b"]
s2.print(); // ["s2a", "s2b"]
// works!
Stack.prototype.push.call(s1, "s1c");
s1.print(); // ["s1a", "s1b", "s1c"]
Pros:
this.arr is not directly accessible
method code is only defined once, not per instance
s1.push(x) works and so does Stack.prototype.push.call(s1, x)
Cons:
The bind call creates four new wrapper functions on every instantiation (but the code is much smaller than creating the internal push/pop/empty/size functions every time).
The code is a little complicated
If i have a Javascript object defined as:
function MyObj(){};
MyObj.prototype.showAlert = function(){
alert("This is an alert");
return;
};
Now a user can call it as:
var a = new MyObj();
a.showAlert();
So far so good, and one can also in the same code run another instance of this:
var b = new MyObj();
b.showAlert();
Now I want to know, how can I hold the number of instances MyObj?
is there some built-in function?
One way i have in my mind is to increment a global variable when MyObj is initialized and that will be the only way to keep track of this counter, but is there anything better than this idea?
EDIT:
Have a look at this as suggestion here:
I mean how can I make it get back to 2 instead of 3
There is nothing built-in; however, you could have your constructor function keep a count of how many times it has been called. Unfortunately, the JavaScript language provides no way to tell when an object has gone out of scope or has been garbage collected, so your counter will only go up, never down.
For example:
function MyObj() {
MyObj.numInstances = (MyObj.numInstances || 0) + 1;
}
new MyObj();
new MyObj();
MyObj.numInstances; // => 2
Of course, if you want to prevent tampering of the count then you should hide the counter via a closure and provide an accessor function to read it.
[Edit]
Per your updated question - there is no way to keep track of when instances are no longer used or "deleted" (for example by assigning null to a variable) because JavaScript provides no finalizer methods for objects.
The best you could do is create a "dispose" method which objects will call when they are no longer active (e.g. by a reference counting scheme) but this requires cooperation of the programmer - the language provides no assistance:
function MyObj() {
MyObj.numInstances = (MyObj.numInstances || 0) + 1;
}
MyObj.prototype.dispose = function() {
return MyObj.numInstances -= 1;
};
MyObj.numInstances; // => 0
var a = new MyObj();
MyObj.numInstances; // => 1
var b = new MyObj();
MyObj.numInstances; // => 2
a.dispose(); // 1 OK: lower the count.
a = null;
MyObj.numInstances; // => 1
b = null; // ERR: didn't call "dispose"!
MyObj.numInstances; // => 1
Create a static property on the MyObj constructor called say count and increment it within the constructor itself.
function MyObj() {
MyObj.count++;
}
MyObj.count = 0;
var a = new MyObj;
var b = new MyObj;
alert(MyObj.count);
This is the way you would normally do it in say Java (using a static property).
var User = (function() {
var id = 0;
return function User(name) {
this.name = name;
this.id = ++id;
}
})();
User.prototype.getName = function() {
return this.name;
}
var a = new User('Ignacio');
var b = new User('foo bar');
a
User {name: "Ignacio", id: 1}
b
User {name: "foo bar", id: 2}
Using ES6 Classes MDN syntax - we can define a static method:
The static keyword defines a static method for a class. Static methods are called without instantiating their class and cannot be called through a class instance. Static methods are often used to create utility functions for an application.
class Item {
static currentId = 0;
_id = ++Item.currentId; // Set Instance's this._id to incremented class's ID
// PS: The above line is same as:
// constructor () { this._id = ++Item.currentId; }
get id() {
return this._id; // Getter for the instance's this._id
}
}
const A = new Item(); // Create instance (Item.currentId is now 1)
const B = new Item(); // Create instance (Item.currentId is now 2)
const C = new Item(); // Create instance (Item.currentId is now 3)
console.log(A.id, B.id, C.id); // 1 2 3
console.log(`Currently at: ${ Item.currentId }`); // Currently at: 3
PS: if you don't want to log-expose the internal currentId property, make it private:
static #currentId = 0;
_id = ++Item.#currentId;
Here's an example with constructor and without the getter:
class Item {
static id = 0;
constructor () {
this.id = ++Item.id;
}
getID() {
console.log(this.id);
}
}
const A = new Item(); // Create instance (Item.id is now 1)
const B = new Item(); // Create instance (Item.id is now 2)
const C = new Item(); // Create instance (Item.id is now 3)
A.getID(); B.getID(); C.getID(); // 1; 2; 3
console.log(`Currently at: ${ Item.id }`); // Currently at: 3
what about such method?
var Greeter = (function ()
{
var numInstances;
function Greeter(message)
{
numInstances = (numInstances || 0) + 1;
this.greeting = message;
}
Greeter.prototype.greet = function ()
{
return "Hello, " + this.greeting;
};
Greeter.prototype.getCounter = function ()
{
return numInstances;
};
return Greeter;
})();
var greeter = new Greeter("world");
greeter.greet();
greeter.getCounter();
var newgreeter = new Greeter("new world");
newgreeter.greet();
newgreeter.getCounter();
greeter.getCounter();
Keeping a global count variable and incrementing every time is an option. Another option is to call counter method after each instance creation by hand (the worst thing I could imagine). But there is another better solution.
Every time we create an instance, the constructor function is being called. The problem is the constructor function is being created for each instance, but we can have a count property inside __proto__ which can be the same for each instance.
function MyObj(){
MyObj.prototype.addCount();
};
MyObj.prototype.count = 0;
MyObj.prototype.addCount = function() {
this.count++;
};
var a = new MyObj();
var b = new MyObj();
This is our a and b variables after all:
Eventually, JS is going to have built-in proxy capability, which will have low-level access to all kinds of things which happen in the background, which will never be exposed to front-end developers (except through the proxy -- think magic-methods in languages like PHP).
At that time, writing a destructor method on your object, which decrements the counter might be entirely trivial, as long as support for destruction/garbage-collection as a trigger is 100% guaranteed across platforms.
The only way to currently, reliably do it might be something like creating an enclosed registry of all created instances, and then manually destructing them (otherwise, they will NEVER be garbage-collected).
var Obj = (function () {
var stack = [],
removeFromStack = function (obj) {
stack.forEach(function (o, i, arr) {
if (obj === o) { arr.splice(i, 1); }
makeObj.count -= 1;
});
};
function makeObj (name) {
this.sayName = function () { console.log("My name is " + this.name); }
this.name = name;
this.explode = function () { removeFromStack(this); };
stack.push(this);
makeObj.count += 1;
}
makeObj.checkInstances = function () { return stack.length; };
makeObj.count = 0;
return makeObj;
}());
// usage:
var a = new Obj("Dave"),
b = new Obj("Bob"),
c = new Obj("Doug");
Obj.count; // 3
// "Dave? Dave's not here, man..."
a.explode();
Obj.count; // 2
a = null; // not 100% necessary, if you're never going to call 'a', ever again
// but you MUST call explode if you ever want it to leave the page's memory
// the horrors of memory-management, all over again
Will this pattern do what you want it to do?
As long as:
you don't turn a into something else
you don't overwrite its explode method
you don't mess with Obj in any way
you don't expect any prototype method to have access to any of the internal variables
...then yes, this method will work just fine for having the counter work properly.
You could even write a general method called recycle, which calls the explode method of any object you pass it (as long as its constructor, or factory, supported such a thing).
function recycle (obj) {
var key;
obj.explode();
for (key in obj) { if (obj.hasOwnProperty(key)) { delete obj[key]; } }
if (obj.__proto__) { obj.__proto__ = null; }
}
Note - this won't actually get rid of the object.
You'll just have removed it from the closure, and removed all methods/properties it once had.
So now it's an empty husk, which you could reuse, expressly set to null after recycling its parts, or let it be collected and forget about it, knowing that you removed necessary references.
Was this useful?
Probably not.
The only time I really see this as being of use would be in a game where your character might only be allowed to fire 3 bullets at a time, and he can't shoot a 4th until the 1st one on screen hits someone or goes off the edge (this is how, say, Contra worked, in the day).
You could also just shift a "disappeared" bullet off the stack, and reuse that bullet for any player/enemy by resetting its trajectory, resetting appropriate flags, and pushing it back onto the stack.
But again, until proxies allow us to define "magic" constructor/destructor methods, which are honoured at a low-level, this is only useful if you're going to micromanage the creation and destruction of all of your own objects (really not a good idea).
My solution is creating an object store instance count and a function to increase them in prototype.
function Person() {
this.countInst();
}
Person.prototype = {
constructor: Person,
static: {
count: 0
},
countInst: function() {
this.static.count += 1;
}
};
var i;
for (i = 0; i < 10; i++) {
var p = new Person();
document.write('Instance count: ');
document.write(p.static.count);
document.write('<br />');
}
Here is my plunker: https://plnkr.co/edit/hPtIR2MQnV08L9o1oyY9?p=preview
class Patient{
constructor(name,age,id){
Object.assign(this,{name, age, id});
}
static patientList = []; // declare a static variable
static addPatient(obj){
this.patientList.push(...obj); // push to array
return this.patientList.length; // find the array length to get the number of objects
}
}
let p1 = new Patient('shreyas',20, 1);
let p2 = new Patient('jack',25, 2);
let p3 = new Patient('smith',22, 3);
let patientCount = Patient.addPatient([p1,p2,p3]); // call static method to update the count value with the newly created object
console.log(Patient.patientList);
console.log(patientCount);
Is there a JavaScript pattern which mimics "Protected" object properties like what you see in languages like C++ ??
Basically, I'd like to create an Object A which has a number of "protected" object properties which can be accessed ONLY from methods which are defined from the prototype of Object A. i.e. - NOT accessible publicly from non-prototyped methods of A.
For instance, ideally would be like so:
function A(){
var prop1 = 1;
}
A.prototype.myFunc = function(){
var newVar = this.prop1; //newVar now is equivalent to 1
}
var instanceOfA = new A();
var newVar2 = instanceOfA.prop1; //error given as prop1 is "protected"; hence undefined in this case
BTW - I do not want the pattern of privileged member functions accessing private properties since the member function is still public.
There is no object property that can only be accessed from prototyped methods of A and not from non-prototyped methods of A. The language doesn't have that type of feature and I'm not aware of any work-around/hack to implement it.
Using Doug Crockford's methods, you can create member properties that can only be accessed from predefined non-prototyped methods (those defined in the constructor). So, if you're trying to limit access only to a predefined set of methods, this will accomplish that. Other than that, I think you're out of luck.
If you want other ideas, you'd probably get more help if you describe more about what you're actually trying to accomplish in your code rather than just how to emulate a feature in another language. Javascript is so much different than C++ that it's better to start from the needs of the problem rather than try to find an analogy to some C++ feature.
You cannot do it in Javascript.
I found a way for creating protected members. Therefor I call the base constructor and return an object with the protected members at the same time:
var protected = BaseClass.call(this);
Here an example:
function SignedIntegerArray(size)
{
var public = this;
var protected = {};
// private property:
var _maxSize = 10000;
// protected property:
protected.array = [];
// public property:
public.Length = size;
if(!isInteger(size) || size < 0 || size > _maxSize) { throw "argument exception"; }
for(var index = 0; index != size; index++) { protected.array[index] = 0; }
// private method:
function isInteger(i) { return i == i + 0 && i == ~~i; }
// protected method:
protected.checkIndex = function(index) { return index >= 0 && index < size; }
// public methods:
public.SetValue = function(index, value) { if(protected.checkIndex(index) && isInteger(value)) { protected.array[index] = value; } };
public.GetValue = function(index) { if(protected.checkIndex(index)) { return protected.array[index]; } else { throw "index out of range exception"; }}
return protected;
}
function FloatArray(size, range)
{
var public = this;
var protected = SignedIntegerArray.call(this, size); // call the base constructor and get the protected members
// new private method, "isInteger" is hidden...
function isFloat(argument) { return argument != ~~argument; }
// ...but "checkIndex" is accessible
public.SetValue = function(index, value) { if(protected.checkIndex(index) && isFloat(value) && value >= public.MinValue && value <= public.MaxValue) { protected.array[index] = value; } };
// new public properties:
public.MinValue = -range;
public.MaxValue = range;
return protected; // for sub-classes
}
function newObject(className, args) { return new function() { className.apply(this, args)}} // you need to use function.call or function.apply to initialize an object. otherwise the protected-object is empty.
window.addEventListener("load", function()
{
var o = newObject(FloatArray, [4, 50.0]);
o.SetValue(3, 2.1);
console.log(o.GetValue(3));
console.log(o.Length); // property from the base-class
});
This is probably what you're looking for: http://javascript.crockford.com/private.html
function ClassA(init)
{
var protected = {};
protected.prop = init * 10;
if(this.constructor != ClassA) { return protected; }
}
function ClassB()
{
var protected = ClassA.call(this, 5); //console.log(protected.prop);
}
//var a = new ClassA(123);
//var b = new ClassB();
I was interested to find a way to answer your question, and here's what I was able to do.
You'll need this helper:
var ProtectedHandler = (function () {
/// <Sumarry>
/// Tool to handle the protected members of each inheritance.
/// </Summary>
/// <param name="current">Current protected variable.</param>
/// <param name="args">The arguments variable of the object.</param>
/// <param name="callback">The function to initialise the variable in the 'object'.</param>
/// <param name="isParent">Is this the ultimate base object.</param>
function ProtectedHandler(current, args, callback, isParent) {
this.child = getChild(args);
if (callback)
this.callback = callback;
if (isParent)
this.overrideChild(current);
}
// Get the ProtectedHandler from the arguments
var getChild = function (args) {
var child = null;
if (args.length > 0 && (child = args[args.length - 1]) && child.constructor === ProtectedHandler)
return child;
};
// Chain Initialise the protected variable of the object and its inheritances.
ProtectedHandler.prototype.overrideChild = function (newValue) {
if (this.callback != null) {
this.callback(newValue);
}
if (this.child != null) {
this.child.overrideChild(newValue);
}
};
// Static function to create a new instance of the protectedHandler object.
ProtectedHandler.handle = function (protected, arguments, callback, isParent) {
return new ProtectedHandler(protected, arguments, callback, isParent);
};
return ProtectedHandler;
})();
This helper will allow you to handle multiple inheritances. The trick is to copy the protected variable from the base object to your new object (child).
To prove you it's working, here's an example:
// That's the default extends function from typescript (ref: http://www.typescriptlang.org/)
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var BaseClass = (function () {
function BaseClass() {
// Members
var private = {},
protected = {},
public = this;
// Constructor
ProtectedHandler.handle(protected, arguments, function () {
protected.type = "BaseClass";
}, true);
// Methods
protected.saySomething = function () {
return "Hello World";
};
public.getType = function () {
return protected.type;
};
}
return BaseClass;
})();
var Person = (function (_super) {
__extends(Person, _super);
function Person(name) {
// Members
var private = {},
protected = {},
public;
// Constructor
_super.call(public = this, ProtectedHandler.handle(protected, arguments, function (p) {
protected = p; //This is required to copy the object from its base object.
protected.name = name;
protected.type = "Person";
}));
//Method
public.getName = function () {
return protected.name;
};
public.saySomething = function () {
return protected.saySomething();
};
}
return Person;
})(BaseClass);
var Child = (function (_super) {
__extends(Child, _super);
function Child(name) {
// Members
var private = {},
protected = {},
public;
// Constructor
_super.call(public = this, name, ProtectedHandler.handle(protected, arguments, function (p) {
protected = p; //This is required to copy the object from its base object.
protected.type = "Child";
}));
//Method
public.setName = function (value) {
return protected.name = value;
};
}
return Child;
})(Person);
And here's the tests:
var testBase = new BaseClass();
testBase.getType(); //"BaseClass"
testBase.saySomething; //undefined
var testPerson = new Person("Nic");
testPerson.getType(); //"Person"
testPerson.saySomething(); //"Hello World"
testPerson.name; //undefined
testPerson.getName() //"Nic"
testPerson.setName; //undefined
var testChild = new Child("Bob");
testChild.getType(); //"Child"
testChild.saySomething(); //"Hello World"
testChild.name; //undefined
testChild.getName(); //"Bob"
testChild.setName("George");
testChild.getName(); //"George"
There is a pattern that I have come to like that does not work the same way as protected access does in most languages, but provides a similar benefit.
Basically, use a builder method to create a closure for properties, and then have that method create a "full" object with liberal access as well as an "exposed" object with more limited access. Place the exposed object into a property of the full object, and return that full object to the caller.
The caller can then make use of the full object (and pass that to other appropriate collaborators), but provide only the exposed object to collaborators that should have the more restricted access.
A contrived example…
// Ring employs a typical private/public pattern while
// RingEntry employs a private/exposed/full access pattern.
function buildRing( size ) {
var i
, head = buildRingEntry( 0 )
, newEntry;
;
head.setNext( head );
for( i = size - 1; i ; i-- ) {
newEntry = buildRingEntry( i );
newEntry.setNext( head.getNext() );
head.setNext( newEntry );
}
function getHead() { return head.exposed; }
return {
getHead : getHead
}
}
function buildRingEntry( index ) {
var next
, exposed
;
function getIndex() { return index; }
function setNext( newNext ) { next = newNext; }
function getNextFullEntry() { return next; }
function getNextExposedEntry() { return next.exposed; }
exposed = {
getIndex : getIndex
, getNext : getNextExposedEntry
};
return {
getIndex : getIndex
, setNext : setNext
, getNext : getNextFullEntry
, exposed : exposed
};
}
If we use that to build a ring of 4 entries ring = buildRing(4);, then ring.getHead().getIndex() gives us 0, ring.getHead().getNext().getIndex() gives us 1, ring.getHead().getNext().getNext().getIndex() gives us 2, etc.
If we try to execute ring.getHead().setNext({}) or ring.getHead().getNext().setNext({}), however, we get an error because setNext is not a property of an exposed entry object.
Caveat:
Since this is in the family of patterns that build the methods again in a new closure for each new object, it is not suitable for situations in which a very high volume of instantiation may be needed.
Take a look at workaround proposed by Maks on his website: Emulating protected members in JavaScript
It emulates protected access level to methods and properties of an object.