Prototypes, prototypal inheritance, and prototype chain in JavaScript

In this article, we will dive deep into the concept of prototypes: why JavaScript incorporates them and how we can harness their power. We will also learn about prototypal inheritance and how a prototype chain is created. Let's get started with a few highlighting points:

While everything in JavaScript is an object, there are technical names for different data types, e.g., string, boolean, etc. For the sake of consistency, we will refer to them all as objects in this article.

We will also refer to a prototype by the name of its constructor. For example, we will call it an Object prototype when an object is created using the Object constructor.

Prototype

A prototype is an object that contains methods and properties we can use to work with objects. Different prototypes contain different methods and properties. For example, the Object prototype contains different methods and properties compared to those in the Array prototype.

As you already know, a prototype is created when you create an object in JavaScript. Objects can be created in two ways: by using built-in constructors or by using custom constructor functions. Let's take a look.

Built-in constructor

const matt = {
  age: 30,
  occupation: 'software developer',
};

console.log(matt.__proto__); // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Object.prototype); // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}

In the above example, we've created an object called matt using the built-in Object constructor. As a result, matt's prototype gets the methods and properties of the Object prototype.

The Object prototype is the base prototype in JavaScript. While all objects have their respective methods and properties within their prototypes, they also inherit methods and properties from the Object prototype.

Good to know that while it's possible to add methods and properties to built-in prototypes, it's generally not recommended.

Custom constructor

Besides using the built-in constructors, we can use custom constructor functions to create objects in JavaScript.

function Person(age, occupation) {
  this.age = age;
  this.occupation = occupation;
}
const john = new Person(30, 'software developer');

console.log(Person.prototype); // {constructor: ƒ}
console.log(john.__proto__); // {constructor: ƒ}

In this code, we've created a constructor function called Person and used it to create an object called john. As per the rule, both the Person function and the john object get the same empty prototype object where we can add custom methods and properties.

Person.prototype.introduce = function () {
  return `Hi, I'm a ${this.age} years old ${this.occupation}`;
};

console.log(john.__proto__); // {introduce: ƒ, constructor: ƒ}

In this code, we've added the introduce method to the Person constructor's prototype. So, john and any other objects created using this constructor function can now access and utilize this method, as you can see in the following example.

console.log(john.introduce()); // Hi, I'm a 30 years old software developer

Prototypal inheritance

Prototypal inheritance is a mechanism that enables objects to inherit and utilize methods and properties from other prototypes. Let's explore this with an example.

Let's use the hasOwnProperty method on john, even though this method doesn't exist directly within the john object or its own prototype:

console.log(john.hasOwnProperty('age')); // true

This works! But how? Here comes the prototypal inheritance into play.

As you know, every JavaScript object inherits methods and properties from the base Object prototype, which contains the hasOwnProperty method. Therefore, john inherits the method and can utilize it.

This process of inheriting and utilizing methods and properties from other prototypes is known as prototypal inheritance.

Prototype chain

A prototype chain is a sequence of connections created when an object accesses methods and properties from other prototypes. When you use a method or property on an object that doesn't exist directly within the object or its own prototype, JavaScript searches for the method or property in the prototypes inherited by that object.

Consequently, a chain of connections is created between that object and its inherited prototypes, which is known as the prototype chain.

Why prototypes?

With prototypes, we can add methods and properties to a constructor function's prototype that other objects can inherit and utilize. This helps us write reusable code, resulting in increased performance and efficiency of our applications.

Without the prototypes, we would recreate the same methods and properties every time we create an object. This redundancy would result in inefficient memory usage and inferior performance.

This wraps up our discussion of the concept of prototypes, prototypal inheritance, and prototype chain in JavaScript. I hope this gives you a good understanding of how prototypes work, why they exist, and how we can utilize this JavaScript feature to build efficient and performant applications.

Share this article with your friends

Copy URL

Elevate your JavaScript and freelance journey

Supercharge your JavaScript skills and freelance career. Subscribe now for expert tips and insights!