What is a Prototype? Why Use Prototypes in JavaScript and How They Work

 


Java Script is a powerful programming language that plays a major role in web development. it enables developers to create interactive and dynamic web pages, making it an important part of web development. One of the most confusing topic related to Java Script that confuses beginners but it is essential to learn for mastering the language is prototypes.


In this blog, we will delve into the concept of prototypes in JavaScript covering all the topics related to prototypes and by the end of the blog, you will have a solid understanding of prototypes in JavaScript and how to leverage them in code to create more robust and maintainable applications.


What is a Prototype in JavaScript?

Definition of Prototype

In JavaScript, Prototype is an object from which other objects inherit properties and methods. Every JavaScript Object has prototypes which acts as blueprint for that object. This allows Object to share common features and behaviours, which helps in code re-usability and efficiency.

Explanation of Prototype Chain    

Prototype chaining is a concept in JavaScript inheritance model. It is a chain of linked objects that facilitate the inheritance of properties and methods. If we try to access a property or method on an object Javascript first looks at the object itself. if it dosen't find the property or method there it will try to look on that objects prototype. This process continues up the chain until the property is find or if the end of chain is returned where the property of method will be null.

Examples of Prototypes in JavaScript

Let's look at some examples to understand prototypes and the prototype chain better.

Example 1: Basic Object Prototype

let animal = { eats: true, walk() { console.log("Animal walks"); } }; let rabbit = { jumps: true }; // Setting rabbit's prototype to animal rabbit.__proto__ = animal; console.log(rabbit.eats); // true rabbit.walk(); // Animal walks(code-box)

In this example:

  • animal is an object with a property eats and a method walk.
  • rabbit is an object with a property jumps.
  • By setting rabbit.__proto__ = animal, we make animal the prototype of rabbit.
  • As a result, rabbit can access the properties and methods of animal through the prototype chain.

Example 2: Function Prototype

function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log(`Hello, my name is ${this.name}`); }; let john = new Person("John"); john.sayHello(); // Hello, my name is John(code-box)

In this example:

  • Person is a constructor function.
  • We add a method sayHello to Person.prototype.
  • When we create a new instance john using new Person("John"), it inherits the sayHello method from Person.prototype.

Example 3: Class Prototype (ES6)

class Car { constructor(model) { this.model = model; } drive() { console.log(`${this.model} is driving`); } } let tesla = new Car("Tesla Model S"); tesla.drive(); // Tesla Model S is driving(code-box)

In this example:

  • Car is a class with a constructor method and a drive method.
  • Instances of Car, such as tesla, inherit the drive method from the Car prototype.
With these examples you will get to know how prototypes works in JavaScript and how that enables inheritance through prototype chain.

Why use Prototypes in JavaScript?

Benefits of using Prototypes

Prototypes in JavaScript offer several advantages that can enhance the efficiency of code. The primary benefits of using prototypes are

1. Memory Efficiency

The first and foremost benefit of using prototype is memory efficiency. When properties or methods defines on prototypes they are shared among all instances of that particular object, so rather than being duplicate for each instance. This results in substantial memory saving, especially when creating many instances.

Like In this example 2 shown above, sayHello is defined on Person.prototype, so all instances of Person share the same method, avoiding redundancy and saving memory.

2. Shared Methods Among Instances

Prototypes allows methods to be shared among all instances of an object, ensuring consistence and reducing code duplication. This helps to update or change method in one place without affecting individual instances.

Example
function Car(model) {
  this.model = model;
}

Car.prototype.drive = function() {
  console.log(`${this.model} is driving`);
};

let car1 = new Car("Tesla");
let car2 = new Car("BMW");

car1.drive(); // Tesla is driving
car2.drive(); // BMW is driving(code-box)

Both car1 and car2 share the drive method, which is defined on the prototype, ensuring that any change to drive will be reflected across all instances. 

How Prototypes Work in JavaScript?

The __proto__ Property

The `__proto__` Property is an internal property ob objects that points to the prototype object from which that object inherits its properties and methods. Even though it is not permissible to use `__proto__` directly in modern code due to performance issues and potential cross browser compatibility issues. it can be helpful for understanding how prototype inheritance works.

The prototype Property of Functions

In JavaScript, every function has a prototype property, which is also an object. it is use when the function is used as a constructor with the `new` keyword. The newly created object's __proto__ property is set to the constructor function's prototype object, enabling inheritance of properties and methods.

How Objects Inherit Properties and Methods

When we try to access property or method on an object, JavaScript first look at the object itself, If it doesn't find the property or method there, it looks at the object's prototype (i.e., the object referenced by __proto__). This process continues up the prototype chain until the property or method is found or the end of the chain is reached (null).

Example Demonstrating Inheritance Through Prototypes

Here's an example demonstrating how inheritance through prototypes works in JavaScript: Imagine we're creating a system to manage different types of user accounts in a web application, such as admin and regular users.

// Constructor function for User
function User(username) {
  this.username = username;
}

// Adding a method to the prototype of User
User.prototype.login = function() {
  console.log(`${this.username} has logged in.`);
};

// Creating instances of User
let adminUser = new User("adminUser");
let regularUser = new User("regularUser");

// Using the shared method
adminUser.login(); // adminUser has logged in.
regularUser.login(); // regularUser has logged in.

// Checking prototypes
console.log(adminUser.__proto__ === User.prototype); // true
console.log(regularUser.__proto__ === User.prototype); // true(code-box)

In this example:

  • User is a constructor function for general user accounts.
  • The login method is added to User.prototype, making it available to all instances of User.

Real-World Example with ES6 Class and Inheritance

Now let’s extend this example by creating a PremiumUser class that inherits from the User class.

// Base class for User
class User {
  constructor(username) {
    this.username = username;
  }
}

// Adding the login method to the prototype of User
User.prototype.login = function() {
  console.log(`${this.username} has logged in.`);
};

// Derived class for PremiumUser
class PremiumUser extends User {
  constructor(username) {
    super(username); // Call the parent class constructor
  }
  
  accessPremiumContent() {
    console.log(`${this.username} is accessing premium content.`);
  }
}

// Creating instances of PremiumUser
let premiumUser1 = new PremiumUser("premiumUser1");
let premiumUser2 = new PremiumUser("premiumUser2");

// Using inherited and own methods
premiumUser1.login(); // premiumUser1 has logged in.
premiumUser1.accessPremiumContent(); // premiumUser1 is accessing premium content.

premiumUser2.login(); // premiumUser2 has logged in.
premiumUser2.accessPremiumContent(); // premiumUser2 is accessing premium content.

// Checking prototypes
console.log(premiumUser1.__proto__ === PremiumUser.prototype); // true
console.log(premiumUser1.__proto__.__proto__ === User.prototype); // true(code-box)

In this example:

  • User is the base class for user accounts with a login method.
  • PremiumUser extends User and adds an additional method, accessPremiumContent.
  • PremiumUser inherits the login method from User, and also has its own method accessPremiumContent.
  • The prototype chain shows that premiumUser1.__proto__ is PremiumUser.prototype, and PremiumUser.prototype.__proto__ is User.prototype.

Conclusion

Understanding prototypes in JavaScript is important for efficient memory usage and inheritance. Prototypes enables us to shared methods across instances, ensuring consistent and reducing redundancy. Mastering Prototypes, whether through traditional constructor functions or modern ES6 classes, ensures in enhancing code maintainability and performance, making JavaScript applications more scalable and effective.

Additional Resources

Post a Comment

0 Comments
* Please Don't Spam Here. All the Comments are Reviewed by Admin.

#buttons=(Ok, Go it!) #days=(20)

Our website uses cookies to enhance your experience. Learn More
Ok, Go it!