JavaScript Prototype


JavaScript is an object-oriented language, and one of its key features is the prototype. The prototype in JavaScript allows objects to share properties and methods, which promotes code reuse and efficient memory management. Understanding how prototypes work is fundamental to mastering object-oriented programming in JavaScript.


1. What is a JavaScript Prototype?

Every JavaScript object has a prototype property. This prototype is itself an object, and it allows other objects to inherit properties and methods from it. In simpler terms, a prototype is a blueprint for objects, and it plays a crucial role in inheritance and shared behavior in JavaScript.

Prototype Chain

JavaScript uses a prototype chain to link objects to their prototypes. If a property or method is not found directly on the object, JavaScript will look for it on the object's prototype, and then continue looking on the prototype's prototype, and so on, until it either finds the property or reaches the end of the chain (null).

Syntax of Prototype

object.prototype.propertyName = value;

2. How Prototypes Work in JavaScript

In JavaScript, when you create an object, the prototype of that object is automatically set to the prototype of the constructor function used to create it. For example, when you create a new object using a constructor function, the object inherits properties and methods from that constructor’s prototype.

Example: Using Prototype with Constructor Functions

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

Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound.`);
};

const dog = new Animal('Dog');
dog.speak();  // Output: Dog makes a sound.

Explanation:

  • The Animal constructor function has a speak method on its prototype. This means that all instances of Animal will have access to the speak method.
  • In the example, dog is an instance of Animal, and it can access the speak method because it's inherited from the prototype.

3. Accessing the Prototype of an Object

You can access the prototype of an object using Object.getPrototypeOf() or the internal __proto__ property. Both of these approaches provide insight into the prototype chain.

Example: Accessing the Prototype

function Car(make, model) {
  this.make = make;
  this.model = model;
}

Car.prototype.getInfo = function() {
  return `${this.make} ${this.model}`;
};

const myCar = new Car("Toyota", "Corolla");

console.log(Object.getPrototypeOf(myCar));  // Output: { getInfo: [Function (anonymous)] }
console.log(myCar.__proto__);  // Output: { getInfo: [Function (anonymous)] }

Explanation:

  • Object.getPrototypeOf(myCar) and myCar.__proto__ return the prototype of the myCar object, which is the Car constructor’s prototype containing the getInfo method.

4. Prototype Inheritance

One of the most powerful uses of prototypes is inheritance. In JavaScript, objects can inherit properties and methods from other objects via their prototype chain.

Example: Prototype Inheritance

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

Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound.`);
};

function Dog(name, breed) {
  Animal.call(this, name);  // Call the parent constructor
  this.breed = breed;
}

// Inherit from Animal
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log(`${this.name} barks.`);
};

const dog1 = new Dog('Buddy', 'Golden Retriever');
dog1.speak();  // Output: Buddy makes a sound.
dog1.bark();   // Output: Buddy barks.

Explanation:

  • The Dog constructor function inherits from Animal by setting Dog.prototype to an instance of Animal.prototype.
  • The Dog constructor adds its own method bark, while still inheriting the speak method from Animal.

5. Modifying Prototypes

In JavaScript, you can add or modify methods and properties of an object’s prototype at any time, even after the object has been created.

Example: Modifying Prototypes Dynamically

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

const person1 = new Person('Alice');

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

person1.greet();  // Output: Hello, Alice!

Explanation:

  • The Person constructor function didn’t initially have a greet method.
  • After creating person1, we add the greet method to Person.prototype, which is then available to all instances of Person.

6. Prototypes and the instanceof Operator

The instanceof operator in JavaScript checks whether an object is an instance of a constructor function and can also be used to check whether an object’s prototype chain contains a particular prototype.

Example: Using instanceof with Prototypes

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

Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound.`);
};

const dog = new Animal('Dog');

console.log(dog instanceof Animal);  // Output: true
console.log(dog instanceof Object);  // Output: true

Explanation:

  • The instanceof operator checks if dog is an instance of Animal. It returns true because dog is an object that inherits from Animal.prototype.