Prototypal Inheritance
Objects Inheriting From Objects
LinkedIn Hook
Classical OOP says: a class inherits from a class. Java does it. C++ does it. Every textbook shows it.
JavaScript does NOT do that.
In JavaScript, objects inherit from objects — period. There are no real class hierarchies. There's just one object pointing to another object via
__proto__. That's the whole mechanism.Which means when you write a constructor function and want it to inherit from another, three lines matter more than anything else:
Parent.call(this, ...)— borrow the parent constructorChild.prototype = Object.create(Parent.prototype)— link the chainsChild.prototype.constructor = Child— fix the constructor pointerMiss any one of these and your inheritance is broken in a subtle, hard-to-debug way.
In this lesson you'll learn exactly why each line exists, the two common wrong ways people set up inheritance, and why
Object.createis always preferred overnew Parent().Read the full lesson -> [link]
#JavaScript #InterviewPrep #Inheritance #Prototypes #Frontend #CodingInterview #OOP
What You'll Learn
- Why JavaScript inheritance is "objects inherit from objects" rather than class-based
- The 3-line recipe for connecting two constructor functions via their prototypes
- Why
Animal.call(this, name)is required and what goes wrong without it
Objects Inheriting From Objects
Here's the fundamental truth about JavaScript: objects inherit from objects. There are no classes in the traditional sense — just objects linked to other objects through the prototype chain.
In classical OOP languages (Java, C++), you define a class blueprint, and objects are instances of that blueprint. In JavaScript, you create an object, and other objects can point to it as their prototype. That's it. That's inheritance.
Setting Up Inheritance Manually
// Parent "constructor"
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function () {
return this.name + " is eating";
};
// Child "constructor"
function Dog(name, breed) {
Animal.call(this, name); // Call parent constructor with 'this'
this.breed = breed;
}
// Set up inheritance: Dog.prototype should inherit from Animal.prototype
Dog.prototype = Object.create(Animal.prototype);
// Fix the constructor reference (it was overwritten above)
Dog.prototype.constructor = Dog;
// Add Dog-specific methods
Dog.prototype.bark = function () {
return this.name + " says Woof!";
};
const rex = new Dog("Rex", "German Shepherd");
console.log(rex.bark()); // "Rex says Woof!" (own prototype)
console.log(rex.eat()); // "Rex is eating" (inherited from Animal)
console.log(rex.name); // "Rex" (own property)
console.log(rex.breed); // "German Shepherd" (own property)
// The chain:
// rex -> Dog.prototype -> Animal.prototype -> Object.prototype -> null
console.log(rex.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
Why Animal.call(this, name) is Crucial
function Vehicle(type) {
this.type = type;
this.running = false;
}
Vehicle.prototype.start = function () {
this.running = true;
return this.type + " started";
};
function Car(type, brand) {
// WITHOUT Vehicle.call(this, ...), parent properties are NOT initialized
// this.type and this.running would be undefined
Vehicle.call(this, type); // Borrow the parent's constructor logic
this.brand = brand;
}
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car;
const myCar = new Car("Sedan", "Toyota");
console.log(myCar.type); // "Sedan" (set by Vehicle.call)
console.log(myCar.running); // false (set by Vehicle.call)
console.log(myCar.brand); // "Toyota" (set by Car)
console.log(myCar.start()); // "Sedan started" (inherited method)
The Wrong Way to Set Up Inheritance
// WRONG: Dog.prototype = Animal.prototype
// This makes them share the SAME prototype object
// Adding methods to Dog.prototype would add them to Animal.prototype too!
Dog.prototype = Animal.prototype; // BAD!
Dog.prototype.bark = function () {}; // This goes on Animal.prototype too!
// WRONG: Dog.prototype = new Animal()
// This calls the Animal constructor unnecessarily
// and creates parent instance properties on the prototype
Dog.prototype = new Animal(); // BAD - runs constructor, extra properties on prototype
Common Mistakes
- Writing
Child.prototype = Parent.prototype— this makes both prototypes the same object, so adding methods to the child also pollutes the parent. - Writing
Child.prototype = new Parent()— this unnecessarily runs the parent constructor (which may require arguments) and leaves parent instance properties on the prototype. - Forgetting
Parent.call(this, args)inside the child constructor — the child instance never gets the parent's own properties (this.name,this.type, etc.), only its prototype methods.
Interview Questions
Q: How is JavaScript inheritance different from classical inheritance?
In classical OOP (Java, C++), classes inherit from classes. In JavaScript, objects inherit from objects. There are no real classes — just objects linked via the prototype chain. An object delegates property lookups to its prototype object.
Q: Why do we use Object.create(Animal.prototype) instead of new Animal() for setting up inheritance?
new Animal()would call the Animal constructor, creating unnecessary instance properties on the prototype and requiring arguments we may not have.Object.create(Animal.prototype)creates a clean object whose__proto__isAnimal.prototypewithout running the constructor.
Q: Why do we need Dog.prototype.constructor = Dog after setting up inheritance?
When we do
Dog.prototype = Object.create(Animal.prototype), the new prototype object'sconstructorproperty is inherited fromAnimal.prototype, pointing toAnimal. We fix it so thatDog.prototype.constructorcorrectly points toDog, which matters for code that checks.constructor.
Q: How do you set up inheritance between two constructor functions?
Three steps: (1) call the parent constructor inside the child with
Parent.call(this, args)to initialize parent-owned properties; (2) setChild.prototype = Object.create(Parent.prototype)to link the prototype chains; (3) restoreChild.prototype.constructor = Childso.constructorstill points to the right function.
Quick Reference — Cheat Sheet
PROTOTYPAL INHERITANCE — THE RECIPE
Parent:
function Parent(x) { this.x = x; }
Parent.prototype.hello = function(){ ... };
Child:
function Child(x, y) {
Parent.call(this, x); // (1) borrow constructor
this.y = y;
}
Child.prototype = Object.create(Parent.prototype); // (2) link chains
Child.prototype.constructor = Child; // (3) fix constructor
Result chain:
instance -> Child.prototype -> Parent.prototype
-> Object.prototype -> null
Wrong patterns (avoid):
Child.prototype = Parent.prototype // shared object, pollutes parent
Child.prototype = new Parent() // runs constructor, extra props
Previous: Prototype Chain ->
__proto__vs.prototypeNext: Object.create()
This is Lesson 5.2 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.