I think I have misunderstood how Javascript prototypal inheritance works. Specifically, the prototypes internal variables seem to be shared between multiple different sub-ob
You need to forget the idea of classes. There isn't really such a thing in JavaScript as an 'instance of B'. There is only 'some object you obtained by calling the constructor function B'. An object has properties. Some are its "own" properties, others are included by searching the prototype chain.
When you say new A, you're creating one object. Then you assign it as the prototype for B, which means that every call to new B produces a new object that has the same direct prototype, and hence the same counter variable.
In Tim Down's answer, two alternatives are shown. His incrementPublic uses inheritance, but makes the counter variable public (i.e. gives up encapsulation). Whereas incrementInternal makes the counter private but succeeds by moving the code into B (i.e. gives up inheritance).
What you want is a combination of three things:
this.The problem is the contradiction between the last two. I would also say that inheritance is of limited value in JS anyway. It's better to treat it as a functional language:
// higher-order function, returns another function with counter state
var makeCounter = function() {
var c = 0;
return function() { return ++c; };
};
// make an object with an 'increment' method:
var incrementable = {
increment: makeCounter()
};
Personally I tend to avoid constructor functions and prototype inheritance most of the time. They are far less useful in JS than people from an OO background assume.
Update I'd be wary of the statement you quoted in your update:
Private variables only work really well with singleton objects in JavaScript.
That's not really true. An object is just a 'dictionary' of properties, any of which may be functions. So forget objects and think about functions. You can create multiple instances of a function according to some pattern, by writing a function that returns a function. The makeCounter example about is just a simple example of this. makeCounter is not a "singleton object" and doesn't have to be limited to use in singleton objects.