5.3 Prototype Inheritance and Chain in JavaScript

Prototype inheritance and the prototype chain are core aspects of JavaScript, offering a flexible and powerful mechanism for object interaction and inheritance.

Medium - Hard
Advanced Topics
Prototype Inheritance and Chain in JavaScript

JavaScript is a language characterized by its dynamic and flexible nature, largely due to its implementation of prototypal inheritance. Unlike classical inheritance found in languages like Java or C++, where classes inherit from other classes, JavaScript employs prototype inheritance where objects inherit directly from other objects.

Understanding Prototypes

Every JavaScript object has a property called prototype. This is a reference to another object from which the original object inherits properties and methods. The prototype object itself is just a regular object, but its power lies in the prototype chain, through which JavaScript objects inherit features from one another.

The Prototype Property

In JavaScript, functions (which are objects themselves) have a prototype property. This property is not significant for most function objects, except when the function is used as a constructor function. When a function is used with the new keyword to create an object, the newly created object inherits properties from the constructor function's prototype property.

function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name}`);
};

const john = new Person('John');
john.greet(); // Output: Hello, my name is John

In this example, john inherits the greet method from Person.prototype.

The __proto__ Property and Object.getPrototypeOf()

While the prototype property is specific to functions, every object in JavaScript has an internal and hidden property called __proto__ (though it is now considered deprecated in favor of Object.getPrototypeOf()). This property references the object from which it inherits, essentially forming a "chain" of objects linked through their prototypes.

const jane = new Person('Jane');
console.log(jane.__proto__ === Person.prototype); // true
console.log(Object.getPrototypeOf(jane) === Person.prototype); // true

The Prototype Chain

The prototype chain is a fundamental concept in JavaScript, providing a mechanism for objects to inherit properties and methods from other objects. When you attempt to access a property or method on an object, JavaScript first looks at the object itself. If it doesn't find the property, it then looks at the object's prototype, then the prototype's prototype, and so on, until it either finds the property or reaches the end of the prototype chain (which is null).

An Example of Prototype Chain

Consider the following extension of our previous example:

function Professional(title, name) {
  Person.call(this, name);
  this.title = title;
}

Professional.prototype = Object.create(Person.prototype);
Professional.prototype.constructor = Professional;

Professional.prototype.professionalGreet = function() {
  console.log(`Hello, my name is ${this.name}, and I am a ${this.title}`);
};

const janeDoe = new Professional('Engineer', 'Jane Doe');
janeDoe.greet(); // Output: Hello, my name is Jane Doe
janeDoe.professionalGreet(); // Output: Hello, my name is Jane Doe, and I am a Engineer

In this example, Professional inherits from Person. An object created with new Professional(...) will have access to methods defined on Professional.prototype, Person.prototype, and ultimately Object.prototype.

Benefits and Considerations of Prototype Inheritance

Benefits

  • Memory Efficiency: Since inherited properties and methods are defined on the prototype, they are shared among all instances, leading to a more efficient use of memory compared to classical inheritance models where each instance has its own copy of inherited features.
  • Dynamic Modifications: Changes to a prototype are immediately reflected across all objects inheriting from that prototype, allowing for dynamic modifications at runtime.

Considerations

  • Understanding the Prototype Chain: The prototype chain can be both powerful and complex. Misunderstandings can lead to unexpected behavior, especially for developers coming from class-based inheritance languages.
  • Performance: While prototype inheritance is memory efficient, excessively long prototype chains can impact property lookup times, although this is rarely a concern in practice.

By understanding these concepts, developers can leverage the full capabilities of JavaScript, creating more efficient and dynamic applications. Whether building simple scripts or complex web applications, a solid grasp of prototypes and inheritance patterns is invaluable for any JavaScript developer.

Support us ❤️

Buy Us A Coffee