JavaScript Interview Prep
Prototypes & Inheritance

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:

  1. Parent.call(this, ...) — borrow the parent constructor
  2. Child.prototype = Object.create(Parent.prototype) — link the chains
  3. Child.prototype.constructor = Child — fix the constructor pointer

Miss 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.create is always preferred over new Parent().

Read the full lesson -> [link]

#JavaScript #InterviewPrep #Inheritance #Prototypes #Frontend #CodingInterview #OOP


Prototypal Inheritance thumbnail


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

Prototypal Inheritance visual 1


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__ is Animal.prototype without 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's constructor property is inherited from Animal.prototype, pointing to Animal. We fix it so that Dog.prototype.constructor correctly points to Dog, 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) set Child.prototype = Object.create(Parent.prototype) to link the prototype chains; (3) restore Child.prototype.constructor = Child so .constructor still 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 .prototype Next: Object.create()


This is Lesson 5.2 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.

On this page