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?
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
.
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);
};
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();
}
}
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());
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();