Classical vs prototypal inheritance

JavaScript

The short answer

Classical inheritance (used in Java, C++, Python) creates objects from class blueprints — you define a class, then create instances from it. Prototypal inheritance (used in JavaScript) creates objects directly from other objects — there are no classes, objects inherit from other objects through the prototype chain.

Classical inheritance

In classical inheritance, you define a class first, and then create objects from that class. The class is like a blueprint.

// Java-like pseudocode
class Animal {
eat() {
console.log('Eating');
}
}
class Dog extends Animal {
bark() {
console.log('Woof');
}
}
const dog = new Dog();
dog.eat(); // from Animal
dog.bark(); // from Dog

The key idea is: class defines structure, then you create instances from it. You cannot change the class after instances are created (in most classical languages).

Prototypal inheritance

In prototypal inheritance, you do not need a class. You create an object, and other objects can inherit from it directly.

const animal = {
eat() {
console.log('Eating');
},
};
const dog = Object.create(animal);
dog.bark = function () {
console.log('Woof');
};
dog.eat(); // "Eating" — inherited from animal
dog.bark(); // "Woof" — own method

No class keyword, no blueprint. Just objects linking to other objects. The dog object inherits from animal through the prototype chain.

The key differences

1. How objects are created:

  • Classical: Define a class first, then create instances with new
  • Prototypal: Create objects directly from other objects using Object.create or object literals

2. Flexibility:

In prototypal inheritance, you can modify the prototype at any time and all objects that inherit from it get the change:

const animal = {
eat() {
console.log('Eating');
},
};
const dog = Object.create(animal);
const cat = Object.create(animal);
// Add a new method to animal — both dog and cat get it
animal.sleep = function () {
console.log('Sleeping');
};
dog.sleep(); // "Sleeping"
cat.sleep(); // "Sleeping"

In classical inheritance, you usually cannot change a class structure after instances are created.

3. Multiple inheritance:

  • Classical: Most languages do not allow inheriting from multiple classes (to avoid the "diamond problem")
  • Prototypal: You can mix in properties from multiple objects using Object.assign or the spread operator
const canWalk = {
walk() {
console.log('Walking');
},
};
const canSwim = {
swim() {
console.log('Swimming');
},
};
const duck = Object.assign({}, canWalk, canSwim);
duck.walk(); // "Walking"
duck.swim(); // "Swimming"

ES6 classes — classical syntax, prototypal behavior

JavaScript added the class keyword in ES6, but it is important to understand that it is just syntax sugar over prototypal inheritance.

class Animal {
eat() {
console.log('Eating');
}
}
class Dog extends Animal {
bark() {
console.log('Woof');
}
}
const dog = new Dog();

This looks like classical inheritance, but under the hood, it is still prototypal. Dog.prototype is linked to Animal.prototype through the prototype chain. There are no real classes — just objects inheriting from other objects.

// Proof that it is still prototypal
console.log(dog.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true

Which is better?

Neither is objectively better — they are different approaches.

  • Classical inheritance is more structured and rigid. It works well for large teams and complex hierarchies where you want strict type checking.
  • Prototypal inheritance is more flexible and dynamic. It works well for JavaScript's use cases where you need to compose objects from different sources.

In practice, most JavaScript developers use ES6 classes (which look classical) but should understand that prototypal inheritance is what is actually happening underneath.

Interview Tip

The key point interviewers want to hear is that JavaScript uses prototypal inheritance, even when you use the class keyword. Show a simple Object.create example to demonstrate prototypal inheritance, then show a class example and explain it is syntax sugar. If you can explain the difference between the two paradigms clearly, it shows deep understanding of how JavaScript works.

Why interviewers ask this

This question tests whether you know how JavaScript actually works versus how it looks. Many developers use ES6 classes without understanding that JavaScript does not have real classes. Interviewers want to see if you understand this distinction, can explain prototypal inheritance without classes, and know the practical implications (like being able to modify prototypes at runtime).