Inheritance in Object oriented JavaScript

I have 3 objects, Science, Physics and Mathematics.

I want the last two object (Physics and Mathematics)
to inherit the protoype properties of Science.

Yet I want both Mathematics & Physics to update the inherited properties and define theirs. This is done, but I keep getting undefined when I try to access the Science properties and method via an instance of Physics. What could be wrong with my code.

function log(elem) {
  return console.log(elem);
}
//create supertype => Science
function Science() {}

//define Science prototype props
Science.prototype = {
  constructor: Science,
  dificulty: "Variable",
  universal: true,
  type: "science",
  name: "science",
  hasSubFields() {
    return true;
  },
};

//create 2 sub fields : Mathematics and Physics to inherit props from Science
function Mathematics(subField) {
  this.subField = subField;
}
function Physics() {}

//let mathematics & Physics inherit science props
Mathematics.prototype = 
Object.create(Science.prototype);
Physics.prototype = 
Object.create(Science.prototype);
Physics.prototype.constructor = Physics;

//over write Mathematics inherited props and physics
Mathematics.prototype = {
  constructor: Mathematics,
  name: "Mathematics",
  type: "Pure and applied Science",
};

Physics.prototype = {
  name: "Physics",
  dificulty: "80%",
  type: "Physical Science",
  subFields: ["Electricity", "Mechanics", "Sound", "Optics", "Waves"],
};

//make instance of Physics
let mechanics = new Physics();
mechanics.name = "mechanics";
mechanics.subFields = ["linear", "force", "force fileds"];

log(mechanics.universal);

Hello there,

I am a lot more familiar with the class syntax for OOP in JS, but perhaps this will help: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance

Personally, I find it much clearer using:

class Science {
  constructor() {
    this.dificulty = 'Variable';
  }
  hasSubfields() {
    return true;
  }
}

class Mathematics extends Science {
  constructor(subField) {
    this.subField = subField;
  }
}

So, unless you specifically want prototypal behaviour, I would recommend using the class syntax.

2 Likes

Just to add to this @opeolluwa , you’re going to get this behaviour out of the box anyway with the class syntax. There’s very little point doing what you’re doing, you’re effectively trying to write your own version of something that already exists in the language.

As an aside: JS doesn’t support multiple inheritance, so what you’re doing is likely to break down extremely quickly. Also you are attempting to model this as if the objects are real world things which will also cause things to break down very quickly

Composition would work much better than inheritance here (“Overall subject can contain a collection of child subjects”, rather than “Overall subject is a parent of child subject”)

1 Like

Here, you assign Physics.prototype to an object that has all properties of Science.prototype:

 Physics.prototype = Object.create(Science.prototype)

But later, you override that with an object literal:

Physics.prototype = {
   name: "Physics",
   dificulty: "80%",
   type: "Physical Science",
   subFields: ["Electricity", "Mechanics", "Sound", "Optics", "Waves"],
 };

So now, Physics.prototype points to an entirely different object that has no relation whatsoever with the Science.prototype anymore.

1 Like

Here’s how you can use inheritance without class syntax. (I’ve tested this.)

function Science() {

  this.name = "science";

  this.difficulty = "Variable";

  this.universal = true;

  this.type = "science";

  this.hasSubFields = function () {

    return true;

  };

}

//define Science prototype props

Science.prototype.stuff = "stuff";

var science = new Science();

function Physics() {

  Science.call(this);

  this.name = "physics";

  this.type = "Physical Science";

  this.subFields = ["Electricity", "Mechanics", "Sound", "Optics", "Waves"];

}

var physics = new Physics();

console.log(physics.name); // -> physics
console.log(physics.difficulty); // -> Variable
console.log(physics.stuff); // -> undefined

The name parameter in physics class overwrites the “name” parameter in the superclass, inherits “difficulty” and returns undefined for stuff because prototypes are inherited unless they are linked like what you did.

Physics.prototype = Object.create(Science.prototype);

I was considering adding an explanation video using a screen recorder but I wasn’t sure if that would be overkill.

2 Likes