Call parent method in JavaScript class but stll have access to prototype methods inside object instance?

耗尽温柔 提交于 2020-01-03 05:11:07

问题


Is it possible to call parent method in JavaScript class but to still have access to prototype methods from parent and child class. Here is code example:

var Base = function() {

  this.baseMethod = function(){
    return 'baseMethod';
  };

  this.baseInitMethod = function() {
    return 'baseInitMethod';
  }
}


Base.prototype.basePrototypeMethod = function() {
  return "basePrototypeMethod";
};


var Specific = function() {

  Base.call(this);

  this.baseInitMethod = function() {
    // call baseInitMethod from Base class
  }

  this.specificMethod = function(){
    return 'specificMethod';
  }

  this.specificInitMethod = function() {

    return this.basePrototypeMethod();
  }
}


Specific.prototype.specificPrototypeMethod = function() {
  return 'specificPrototypeMethod' + '-' + this.baseInitMethod();
}


for(var p in Base.prototype) {
   Specific.prototype[p] = Base.prototype[p]
}


var s = new Specific();


console.log(s.baseMethod());

console.log(s.baseInitMethod());

console.log(s.basePrototypeMethod());

console.log(s.specificMethod());

console.log(s.specificInitMethod());

console.log(s.specificPrototypeMethod());

I want to call baseInitMethod in Base class from baseInitMethod method inside Specific class but so that all function calls from above still works. Is that possible?


回答1:


Your Specific.prototype object should inherit from the Base.prototype object. Currently you're copying over all its properties to the object with this code:

for(var p in Base.prototype) {
   Specific.prototype[p] = Base.prototype[p]
}

But you should actually use Object.create to establish a real prototype chain:

Specific.prototype = Object.create(Base.prototype);

Specific.prototype.specificPrototypeMethod = function() {
  return 'specificPrototypeMethod' + '-' + this.baseInitMethod();
}

I want to call baseInitMethod in Base class from baseInitMethod method inside Specific class

Yes. In your Specific constructor, you first need get Base's baseInitMethod instance method, before you overwrite the property of the instance:

function Specific() {
    Base.call(this);

    var parentInitMethod = this.baseInitMethod;
    this.baseInitMethod = function() {
        // call baseInitMethod from Base class:
        parentInitMethod.call(this /*, arguments…*/); 
    }

    …
}

so that all function calls from above still works.

I'm not sure what you mean by that exactly. The specificPrototypeMethod will always call the baseInitMethod of the current instance, which would be Specific's overwritten one not the original that was defined in Base.




回答2:


Here is what you need to do:

var Base = function () {
};
Base.prototype.baseMethod = function () {
    return 'baseMethod';
};
Base.prototype.baseInitMethod = function () {
    return 'baseInitMethod';
};
Base.prototype.basePrototypeMethod = function () {
    return "basePrototypeMethod";
};


var Specific = function () {
    Base.apply(this, arguments);
};
Specific.prototype.baseInitMethod = function () {
    Base.prototype.baseInitMethod.apply(this,arguments);
};

Specific.prototype.specificMethod = function () {
    return 'specificMethod';
};

Specific.prototype.specificInitMethod = function () {
    var basePrototypeMethodCallResult = Base.prototype.basePrototypeMethod.apply(this,arguments);

};



回答3:


You're overwriting the baseInitMethod of Base inside Specific, with Specific's definition, so why would you ever want to call the Base version? If you simply remove the overwrite of the function you should call the Base definition:

var Base = function() {

  this.baseMethod = function(){
    return 'baseMethod';
  };

  this.baseInitMethod = function() {
    return 'baseInitMethod';
  }
}


Base.prototype.basePrototypeMethod = function() {
  return "basePrototypeMethod";
};


var Specific = function() {

  Base.call(this);

  this.baseInitMethod(); // calls the Base definition only

  this.specificMethod = function(){
    return 'specificMethod';
  }

  this.specificInitMethod = function() {

    return this.basePrototypeMethod();
  }
}



回答4:


One might argue "Why always trying to mimic 'classical' behaviour and fuss with call and apply instead of embracing the prototype delegation pattern instead?"

Here is what I would code :

var Base = {

    baseVariable1: "baseValue1",

    baseVariable2: "baseValue2",

    baseMethod: function () {
        return 'baseMethod';
    },

    baseInitMethod: function () {
        return 'baseInitMethod';
    }
}

var Specific = Object.create(Base);

Specific.variable1 = "value1";

Specific.variable2 = "value2";

Specific.specificInitMethod = function () {
    return 'specificInitMethod' + '-' + this.baseInitMethod();
}

Specific.specificMethod = function () {
    return 'specificMethod' + '-' + this.baseInitMethod();
}

var s = Object.create(Specific);

console.log(s.baseInitMethod());

console.log(s.baseVariable1);

console.log(s.baseVariable2);

console.log(s.variable1);

console.log(s.variable2);

console.log(s.baseMethod());

console.log(s.specificInitMethod());

console.log(s.specificMethod());



回答5:


class Parentable {
  get parent() {
    return this.__proto__.__proto__;
  }
} 
class A extends Parentable { 
  say() { 
    console.log('Hello from A'); 
  } 
}
class B extends A {
  say() {
   console.log('Im not A, I am B! But A send you a message:');
   this.parent.say();
  }
}
(new B()).say();


来源:https://stackoverflow.com/questions/26178519/call-parent-method-in-javascript-class-but-stll-have-access-to-prototype-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!