Episode 11 of 11
Prototype Inheritance
Implement inheritance using prototypes — understand how JavaScript class inheritance works under the hood with the prototype chain.
Prototype Inheritance
When you use extends in ES6, JavaScript sets up prototype inheritance behind the scenes. Let us see how inheritance works at the prototype level.
Inheritance with Constructor Functions
function User(name, email) {
this.name = name;
this.email = email;
}
User.prototype.login = function() {
console.log(this.name + ' logged in');
return this;
};
User.prototype.logout = function() {
console.log(this.name + ' logged out');
return this;
};
function Admin(name, email, role) {
User.call(this, name, email); // Call parent constructor
this.role = role;
}
// Set up prototype inheritance:
Admin.prototype = Object.create(User.prototype);
// Add Admin-specific methods:
Admin.prototype.deleteUser = function(user) {
console.log(user.name + ' deleted by ' + this.name);
};
How It Works
// Object.create(User.prototype) creates a new object whose __proto__ is User.prototype
// Setting Admin.prototype to this object links the prototype chains:
admin (instance)
└── __proto__ → Admin.prototype
├── deleteUser()
└── __proto__ → User.prototype
├── login()
├── logout()
└── __proto__ → Object.prototype
Using the Inherited Class
var admin = new Admin('Shaun', 'shaun@example.com', 'super-admin');
admin.login(); // 'Shaun logged in' (from User.prototype)
admin.deleteUser({}); // works (from Admin.prototype)
console.log(admin instanceof Admin); // true
console.log(admin instanceof User); // true
ES6 Class Equivalent
// All of the above is equivalent to:
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
login() {
console.log(this.name + ' logged in');
}
}
class Admin extends User {
constructor(name, email, role) {
super(name, email);
this.role = role;
}
deleteUser(user) {
console.log(user.name + ' deleted');
}
}
// The class syntax does all the prototype wiring for you
Comparison
| Task | Prototype Way | Class Way |
|---|---|---|
| Parent constructor | User.call(this, ...) | super(...) |
| Inherit methods | Admin.prototype = Object.create(User.prototype) | extends User |
| Add methods | Admin.prototype.method = function() {} | method() {} |
Series Summary
You now understand JavaScript OOP from both sides:
- ES6 classes — the clean, modern syntax for OOP
- Prototypes — the underlying mechanism that makes it all work
Key Takeaways
Object.create()creates an object with a specific prototype linkUser.call(this, args)is the prototype equivalent ofsuper(args)- ES6
extendssets up the same prototype chain automatically - Understanding prototypes helps you debug inheritance issues and understand JavaScript deeply