DEV Community

Cover image for Inheritance in JavaScript and understanding the prototype chain
Gordon_Gao
Gordon_Gao

Posted on

Inheritance in JavaScript and understanding the prototype chain

Javascript has an interesting inheritance model, which happens to be completely different from most OOP languages. While it is object-oriented, an object doesn't have a class that it gets its methods from. Instead, it has a prototype.

This is called prototype-based inheritance (as contrasted with class-based inheritance)

It is important to understand the differences between these two as they are not equivalent, and lead to much confusion down the line.

Even though JavaScript has since introduced class keyword for supporting OOP, this is simply syntactic sugar for its prototype-based inheritance model - nothing has fundamentally changed.

Defining a class with the function keyword


Let's have a look at a "class", defined using the function keyword:

function Animal(name, energy) {
  // _secret is a private property, which cannot be accessed with a dot-notation
  const _secret = 100;
  // name and energy are public properties, can be accessed with a dot-notation
  this.name = name;
  this.energy = energy;
  // this function is public, and returns the value of the private _secret property (but prevents it from being modified)
  this.getSecret = () => _secret;
}

// all properties under prototype are shared methods across all instances of a function.
Animal.prototype.sleep = function(energyReplenished) {
  console.log(`${this.name} is sleeping.`);
  this.energy += energyReplenished;
};
Animal.prototype.play = function(energyLost) {
  console.log(`${this.name} is playing.`);
  this.energy -= energyLost;
};


Note: _secret is a private property not because of the _ prefix on its variable name, but because we did not define it specifically as a property on this.

Prototype-based Inheritance


Now let's have a look at inheritance:

function Dog(name, energy, breed) {
  // every instance of Dog will now have a name and energy property.
  Animal.call(this, name, energy); // look at the Animal function above - notice how it takes in `name` and `energy` as the two parameters
  // in addition to the properties created by the Animal function, Dog also has its own properties now as well
  this.breed = breed;
}

// Dog has the same prototypes that are definded in Animal,
Dog.prototype = Object.create(Animal.prototype);

// but also some of its own as well:
Dog.prototype.bark = function () {
  console.log('Woof Woof!');
  this.energy -= 0.1;
}

// Let Dog's constructor point to itself, not Animal
Dog.prototype.constructor = Dog;

Thanks for reading, and I hope you've enjoyed!
Collapse

Top comments (0)