0

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?

2
  • Surely what you want breaks the convention of inheritance? If you want to share a method, create a third class that can be used by both. Commented Oct 3, 2014 at 12:00
  • Can you give a example please? Commented Oct 3, 2014 at 12:14

5 Answers 5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Ohhhh man I feel so stupid :) Answer is so simple I just needed to create reference to parent method before overriding that method in Specific class. Thanks a million. Now I understand why you have 106K rep. You are a ninja :) Thanks again.
1

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 Comments

I know for this. But I do not want all my methods to be in prototype because when you say new Specific() all methods that are inside constructor are recreated again but ones that are in prototype are not recreated again when you say new Specific().
Exactly. And if you want some method to be used out of the Base, you have to define it inside it's prototype. Otherwise, it's just defined in scope of instance of your Base class.
btw: I see no problem that methods are not being recreated. Because they are still accessible via "this" instance. Also - isn't it good that things that are not necessary for recreation, are not being recreated during JS runtime? ;)
0

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

2 Comments

I can not do that because the baseInitMethod is called like public method outside so I need to have it like definition.
Ok thats fine but you should consider avoiding this over-engineered approach as it is convoluted and almost certainly unnecessary. The answer you marked as correct indicated exactly what I was saying.
0

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());

2 Comments

Problem with this approach is that I can not have variables inside Base class and I need variables.
Of course you can, see my edited answer. And there is no class in JS. (I think, even with ES6 and the class and super keywords, it will be just keywords to hide the real prototypal nature of JS). Base is an object. In my case, it is a plain object, so you can add properties, that can point to functions, primitives, or plain objects. In yours, it is a function, but still an object, since functions are objects in JS, certainly not a class.
0
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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.