开发者

Workaround for calling private method in baseclass from subclass in JavaScript

开发者 https://www.devze.com 2023-03-14 18:01 出处:网络
base = function () { this.A = function () { this.B(); } this.B = function () {} // ABSTRACT! var E = function () {
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?

Yes.


I have used the following steps to create a class with private and public scope in JavaScript:

  1. Create a normal prototype chain with only public members
  2. Either mark public methods public or private members as private using a boolean set on the method itself. ( vis. function foo() {}; foo._private = true; )
  3. Instantiate the chain inside an "interface class"
  4. Iterate over the chain instance, creating references to its public members on the interface class
  5. 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().

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号