base = function () {
this.A = function () {
this.B();
}
this.B = function () {} // ABSTRACT!
var E = function () {
alert('I am E');
}
}
sub = function () {
this.B = function () {
alert('I am B');
}
this.D = function () {
E();
}
}
sub.prototype = new base();
Situation 1:
(new sub()).D();
This doesn't work, as expected, since D and E are in different closures. I want to keep E private, since it should never be invoked directly (i.e. on an instance). I understand the reason for not being allowed to access E is to ensure encapsulation, but what can I do? My only two options appear to be to either make it privileged (which like I said, I am against since it will allow it to be called on an instance) or to manually copy it into each of my subclasses as a private method (which isn't much of a solution).
Situation 2:
(new sub()).A();
When I resolve higher up the prototype chain, do I "reset"/start at the e开发者_JS百科nd at the next function call?
I have used the following steps to create a class with private and public scope in JavaScript:
- Create a normal prototype chain with only public members
- Either mark public methods public or private members as private using a boolean set on the method itself. ( vis.
function foo() {}; foo._private = true;
) - Instantiate the chain inside an "interface class"
- Iterate over the chain instance, creating references to its public members on the interface class
- Rebind those references to the chain instance
Here's some code:
function BaseClass() {
this.A = function A() {
this.B();
}
this.B = function B() {}
this.C = function C() {
console.log('I am C');
}
this.C._private = true;
}
function Subclass() {
this.D = function D() {
this.C();
}
this.B = function B() {
console.log('I am B');
}
}
Subclass.prototype = new BaseClass();
function Interface() {
var classScope = new Subclass();
for ( var property in classScope ) {
if ( !classScope[property]._private ) {
this[property] = classScope[property].bind(classScope);
}
}
}
var classInstance = new Interface();
console.log(classInstance);
classInstance.A();
classInstance.B();
classInstance.D();
To see the output, checkout this code pen.
To see it with the code cleaned up a little bit to make the purpose of each expression a little clearer, checkout this code pen.
Note that function C() {}
is fully encapsulated by function Interface() {}
but (new Interface()).D()
still has access to it.
Also, note that (new Interface()).A()
calls Subclass#B()
.
精彩评论