Classical Inheritance in JavaScript
HardWhile JavaScript uses prototypal inheritance, you can implement classical inheritance patterns. Before ES6 classes, this was done with constructor functions and Object.create(). Understanding these patterns helps you understand how extends works under the hood and how to work with older codebases.
Interactive Visualization
Code
1class Animal {
2 constructor(name) {
3 this.name = name
4 }
5 speak() {
6 console.log(`${this.name} makes a sound`)
7 }
8}
Prototype Chain
Chain will appear after class definition
Define the parent class Animal with a constructor and method
1 / 4
Key Insight: extends sets up the prototype chain (Dog.prototype.__proto__ = Animal.prototype). super() calls the parent constructor to initialize inherited properties.
Key Points
- Subclass.prototype = Object.create(Superclass.prototype)
- Call parent constructor: Superclass.call(this, args)
- Fix constructor property after setting prototype
- ES6 extends handles this automatically
- Understanding the pattern helps debug older code
Code Examples
Manual Inheritance Pattern
function Animal(name) { this.name = name; } Animal.prototype.speak = function() { return this.name + " makes a sound"; }; // Dog inherits from Animal function Dog(name, breed) { // Call parent constructor Animal.call(this, name); this.breed = breed; } // Set up prototype chain Dog.prototype = Object.create(Animal.prototype); // Fix constructor property Dog.prototype.constructor = Dog; // Add Dog-specific method Dog.prototype.speak = function() { return this.name + " barks"; }; const dog = new Dog("Rex", "German Shepherd"); console.log(dog.speak()); // "Rex barks" console.log(dog instanceof Dog); // true console.log(dog instanceof Animal); // true
Manual inheritance: call parent constructor, set prototype with Object.create(), fix constructor.
ES6 Equivalent
class Animal { constructor(name) { this.name = name; } speak() { return this.name + " makes a sound"; } } class Dog extends Animal { constructor(name, breed) { super(name); // Calls parent constructor this.breed = breed; } speak() { return this.name + " barks"; } } const dog = new Dog("Rex", "German Shepherd"); // extends desugars to the manual pattern above // super() desugars to Animal.call(this, name)
ES6 class extends handles all the manual prototype setup automatically.
Common Mistakes
- Forgetting to call parent constructor
- Not setting Dog.prototype.constructor back to Dog
- Using Dog.prototype = new Animal() instead of Object.create()
Interview Tips
- Know the manual inheritance pattern
- Understand what extends desugars to
- Know why Object.create() is preferred over new Parent()
- Be able to set up inheritance without class syntax