2

i've got some problems with javascript prototype inheritance when this inheritance is stretched between multiple objects: surely i'm doing something wrong but for the moment i'm failing to understand what.

The whole Prototype's inheritance system seems to lose available methods when extending a prototype that already extends a prototype.

An example:

consider the following Objects

  • object A
    • prototype with extended function ab
    • prototype with extended function cd
  • object B
    • extends A
  • object C
    • extends B
    • prototype with extended function ef
  • object D
    • extends C

here an example of these Objects, as i have defined them:

Object A

function A () {
    this.someproperty = someValue;
}

A.prototype.ab = function () {
    // does something
}

A.prototype.cd = function () {
    // does something
}

Object B

function B () {
    A.call(this);

    this.someOtherProperty = someValue;
}

B.prototype = A.prototype;
B.prototype.constructor = B;

Object C

function C () {
    B.call(this);
}

C.prototype = B.prototype;
C.prototype.constructor = C;

C.prototype.ef = function () {
    // does something
}

Object D

function D () {
    C.call(this);

    this.someOtherProperty = someValue;
}

D.prototype = C.prototype;
D.prototype.constructor = D;

given the example above, i am expecting that initializing a variable as "new D", such variable should have available the methods ab, cd, and ef, accessible with

  • variable.ab()
  • variable.cd()
  • variable.ef()

It seems instead that all of these are undefined.

Please consider that if i initialize "new B" instead:

  • variable.ab()
  • variable.cd()

are defined and working

am i doing something wrong or prototype inheritance cannot be over stretched over multiple objects?

Thank you!

3
  • @mbojko's answer should work below. How are you checking the properties of new D()? For example Object.keys(new D()) will give you the someProperty and someOtherProperty as these belong to the instance, but the methods do not and will not be listed. console.log((new D()).ab) should still give you a function reference though. Commented Sep 11, 2019 at 10:18
  • 1
    In the future, please do not edit questions in a way that invalidates existing answers. Please consider rolling your edit back and accepting the answer that solved the problem. Commented Sep 11, 2019 at 10:18
  • checking again, @mbojko answer was the correct fix, also ES6 syntax was working correctly. Thank you all for the support Commented Sep 11, 2019 at 10:40

2 Answers 2

6
B.prototype = A.prototype;

It's not inheritance, it's overwriting: A.prototype and B.prototype become the same object. It should be

B.prototype = Object.create(A.prototype);
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your reply. I tried this as well, and will update my main answer, but the outcome is the same: the methods of A are undefined when a new D is instantiated
@Mith84 It is good to understand how it works under the hood, however I would suggest using the class syntax instead if you are going to use this kind of inheritance. This way problems such as calling one of your constructors without new are taken care of.
@EuanSmith using ES6 syntax then solves the problem?
Yes class B extends A {...} see MDN
I checked again: prototype extension is indeed working correctly
1

Here is your code re-written with ES6 classes. @mbojko's answer is quite correct (so please accept that one rather than this as @mbojko is directly answering your question), however if you are going to use deep levels of class inheritance of this kind (and many would argue that you shouldn't - I tend to feel for some problems it is the right approach but you certainly need to be cautious) I would suggest using ES6 classes instead - clearer syntax and more guards against incorrect usage.

class A{
  constructor (){
    this.someproperty = 0;
  }

  ab(){
    //...
    return "called ab method"
  }
  cd(){
    //...
  }
}

class B extends A{
  constructor(){
    super();
    this.someOtherProperty = 1;
  }
}

class C extends B{
  ef(){
    //...
  }
}
class D extends C{
  constructor(){
    super();
    this.someOtherProperty = 2;
  }
}

const d=new D();
console.log(d.ab());

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.