Skip to content

Instantly share code, notes, and snippets.

@amerrika
Last active November 3, 2025 14:59
Show Gist options
  • Select an option

  • Save amerrika/34e9f99b4d6a0c37572e9644b6a5e48b to your computer and use it in GitHub Desktop.

Select an option

Save amerrika/34e9f99b4d6a0c37572e9644b6a5e48b to your computer and use it in GitHub Desktop.

Inheritance

After grasping the concept of prototype objects in the first article, Prototypes, we will focus on inheritance. Without delving too deeply or covering all aspects, this article should answer the following questions:

  • How does inheritance work?
  • Why is it an important concept in JavaScript?
  • Why is it useful for us to understand it?

Prototypal inheritance

This type of inheritance is based on the prototype chain. A prototype object is simply a regular object. This is why it's necessary to have a mechanism that allows created objects to inherit methods and properties. We briefly mentioned this mechanism in our "Prototypes" article. It is generally called the internal prototype (historically proto but the use of it has been deprecated).

In what ways can this concept be helpful in JavaScript? Suppose we have three objects, A, B, and C, that are connected by prototypal inheritance. If object B has a property that object A needs but doesn't have, object A can access this property as if it were its own. The same applies if object B needs a property that object C has but object B doesn't. Similarly, object A can access the properties of object C. This demonstrates the importance of the concept: it enables code sharing!

Let's start with examples

To implement such kind of inheritance hierarchy we are going to create three constructor functions:

function Device() {
  this.category = "Device";
  this.subcategory = "Electronics";
  this.getPath = function () {
    return this.category + "/" + this.subcategory;
  };
}

function Usb() {
  this.name = "USB Memory Stick";
}

function Mouse(connectivity, dpi) {
  this.name = "Computer Mouse";
  this.connectivity = connectivity;
  this.dpi = dpi;
  this.getMouseInfo = function () {
    return `A ${this.connectivity} ${this.name} with maximum DPI of ${this.dpi} `;
  };
}

The following code demonstrates this inheritance "magic":

Usb.prototype = new Device();
Mouse.prototype = new Usb();

What happened here? We swapped the initial prototype object of the Usb() constructor with an instance of Device() constructor. Then we did the same with the prototype of Mouse() replacing it with an instance of Usb() constructor.

console.log(Usb.prototype)

img-1

As we can see in the image above, the prototype object of Usb() constructor now contains all the direct properties of the Device() instance (category, subcategory and getPath). We can also see that the internal <prototype> object points to the prototype object of Device() constructor which is empty.

console.log(Mouse.prototype)

img-1 1

As for the prototype object of the Mouse() constructor, we can see that it contains a direct property of the Usb() instance (name). The internal <prototype> points to the prototype object of the Usb() constructor.

These properties and methods are not inherited from Device() constructor but from its instance. We can now modify or even delete the Device() constructor which will have no effect on the Usb(). All we need is one instance from which features will be inherited.

Side effect of replacing prototype object

When we replace prototype object, instead of just adding methods and properties to it, we get side effect for the constructor!

console.log(Usb.prototype.constructor); // Device()
console.log(Mouse.prototype.constructor); // Device()

After inheritance process it's a good idea to again set constructor to default:

Usb.prototype.constructor = Usb;
Mouse.prototype.constructor = Mouse;

console.log(Usb.prototype.constructor); // Usb()
console.log(Mouse.prototype.constructor); // Mouse()

Let's analyze the inheritance process

We're going to create an instance of Mouse() and call the getMouseInfo() method.

const mouseOne = new Mouse("wired", 4800)
console.log(mouseOne.getMouseInfo()) // A wired Computer Mouse with maximum DPI of 4800

This was expected behaviour as the getMouseInfo() is direct method of the mouseOne object. Now, the mouseOne object doesn't have its own getPath() method but it will inherit it and use it as its own.

console.log(mouseOne.getPath()) // Device/Electronics

When calling mouseOne.getPath() JavaScript Engine does the following:

  • looks up own properties of mouseOne and doesn't find the getPath() there
  • identifies the internal <prototype> of the mouseOne (because this refers to the mouseOne) img-2
  • this internal <prototype> points directly to the prototype object of its Mouse() constructor but JavaScript doesn't find the method there either and thus it has to keep looking.
  • the prototype object of the Mouse() constructor also contains internal <prototype> object. Now, this <prototype> points to the prototype object of the Usb() constructor. img-3
  • Finally, JavaScript Engine finds the getPath() method and this method is called as if it was own method of mouseOne.

Follow internal prototypes up to the Object()

Now, because every object in JavaScript has internal <prototype> by following these internal <prototype> objects we can reach the prototype object of the Object() constructor. img-4

Why to put your time and effort in understanding this mechanism?

This inheritance mechanism is difficult to understand. For those just starting to learn JavaScript, I would say it's not that important. On the other hand, I'd say it's important for intermediate learners and those using frameworks/libraries to understand it. In my opinion, the reasons are as follows:

  • Whenever we use Inspect tool to open Console we'll see all this <prototype> objects. It helps to understand their purpose in order not to get confused by them.
  • The same applies when working with frameworks because prototyple inheritance is widely used in JavaScript frameworks and libraries and it's useful to know how all these different methods and properties are inherited.

Resources

  • Object Oriented JavaScript - third edition by Ved Antani and Stoyan Stefanov

Disclaimer

By no means am I a JavaScript expert, so feel free to comment and point to the potential mistakes. I write articles as my learning experience and with hope it can be useful for others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment