mediumFrontend EngineerTechnology
How does prototypal inheritance work in JavaScript, and how does it differ from classical inheritance?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
Interviewer at a large tech company asked:
"Can you explain how JavaScript's prototype chain works? And why does
classin JS not work like classes in Java or C++?"
Suggested Solution
Prototypal Inheritance
Every JavaScript object has a hidden [[Prototype]] property pointing to another object. When you access a property, JS walks up the chain until it finds it or reaches null.
const animal = { eats: true };
const dog = Object.create(animal);
dog.barks = true;
dog.barks; // true (own property)
dog.eats; // true (from animal via prototype chain)
dog.toString; // [Function] (from Object.prototype)
Prototype Chain
dog → animal → Object.prototype → null
class is Syntactic Sugar
class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} makes a noise`; }
}
class Dog extends Animal {
speak() { return `${this.name} barks`; }
}
Under the hood this is:
function Animal(name) { this.name = name; }
Animal.prototype.speak = function() { return `${this.name} makes a noise`; };
function Dog(name) { Animal.call(this, name); }
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.speak = function() { return `${this.name} barks`; };
Key Differences from Classical Inheritance
| Aspect | JavaScript | Java/C++ |
|---|---|---|
| Mechanism | Prototype chain (delegation) | Class-based (copying) |
| Dynamic? | Yes — add methods at runtime | No — fixed at compile time |
| Multiple inheritance | Via mixins/Object.assign | Via interfaces/traits |
instanceof | Checks prototype chain | Checks class hierarchy |
| Objects created from | Other objects | Classes (blueprints) |
Production Gotcha: __proto__ vs prototype
// __proto__ is the ACTUAL prototype of an instance
dog.__proto__ === Animal.prototype; // true
// prototype is a property on constructor functions
Animal.prototype === dog.__proto__; // true
// They are NOT the same thing
Dog.prototype !== Dog.__proto__;
// Dog.prototype → used for instances created by new Dog()
// Dog.__proto__ → Animal.prototype (Dog inherits from Animal)
Why It Matters
- Performance: Deep prototype chains slow property lookup
- Security: Prototype pollution attacks can override Object.prototype
- Libraries: Understanding this is essential for debugging React/Vue internals