Understanding Prototypical Inheritance in JavaScript
7. Prototypical Inheritance
Prototypical inheritance is a feature in JavaScript that allows objects to inherit properties and methods from other objects. This inheritance is achieved through the prototype chain, where objects can have a prototype object that serves as a template from which to inherit methods and properties. This is different from classical inheritance in languages like Java or C++, where classes inherit from other classes.
Basics of Prototypical Inheritance
- Prototype Chain:
- Every JavaScript object has a prototype.
- The prototype is also an object, and it has its own prototype, forming a chain.
- The chain ends with
Object.prototype
, which hasnull
as its prototype.
- Accessing Properties and Methods:
- When a property or method is accessed on an object, JavaScript first looks for it on the object itself.
- If not found, it looks on the object’s prototype, and continues up the prototype chain until it finds the property or reaches the end of the chain.
Creating Prototypal Inheritance
Using Object.create()
The Object.create()
method creates a new object with the specified prototype object and properties.
let personPrototype = {
greet: function () {
console.log('Hello, ' + this.name);
},
};
let john = Object.create(personPrototype);
john.name = 'John';
john.greet(); // Hello, John
In this example:
personPrototype
is an object that has agreet
method.john
is created withpersonPrototype
as its prototype.john
can accessgreet
from its prototype.
Constructor Functions
Before ES6, constructor functions were commonly used to achieve inheritance.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
console.log('Hello, ' + this.name);
};
let jane = new Person('Jane');
jane.greet(); // Hello, Jane
In this example:
Person
is a constructor function.Person.prototype
is used to add methods that should be available to all instances ofPerson
.jane
is an instance ofPerson
, and it can access thegreet
method fromPerson.prototype
.
ES6 Classes
ES6 introduced class
syntax, which is syntactic sugar over the existing prototype-based inheritance. Classes in ES6 make it easier and more intuitive to create and work with prototypes.
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log('Hello, ' + this.name);
}
}
let john = new Person('John');
john.greet(); // Hello, John
In this example:
Person
is a class with a constructor and agreet
method.john
is an instance ofPerson
and can access thegreet
method.
Inheritance with Prototypes
Prototypal inheritance allows objects to inherit from other objects. This can be done using Object.create()
or class inheritance.
Using Object.create()
let animal = {
speak: function () {
console.log(this.sound);
},
};
let dog = Object.create(animal);
dog.sound = 'Woof';
dog.speak(); // Woof
Using ES6 Classes
class Animal {
constructor(sound) {
this.sound = sound;
}
speak() {
console.log(this.sound);
}
}
class Dog extends Animal {
constructor() {
super('Woof');
}
}
let dog = new Dog();
dog.speak(); // Woof
In this example:
Animal
is a base class with aspeak
method.Dog
extendsAnimal
, inheriting its properties and methods.super
is used to call the constructor of the base class.
Prototype Chain
The prototype chain can be visualized as a series of links between objects, where each object has a link to its prototype:
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
console.log('Hello, ' + this.name);
};
let john = new Person('John');
console.log(john.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
Conclusion
Prototypical inheritance in JavaScript is a powerful feature that allows for flexible and efficient object-oriented programming. Understanding how prototypes and the prototype chain work is essential for mastering JavaScript and effectively utilizing its inheritance model. Whether using Object.create()
, constructor functions, or ES6 classes, prototypal inheritance enables code reuse and the creation of complex object hierarchies.