One of the most common senior JavaScript interview questions is:
How does inheritance work in JavaScript?
Many developers answer:
"Using classes."
While technically true, it misses the most important concept.
JavaScript inheritance is actually based on:
Prototypes
Classes are simply syntactic sugar built on top of the prototype system.
To truly understand JavaScript, you must understand:
- Prototypes
- Prototype Chain
- Inheritance
- Constructor Functions
- Object.create()
- How classes work internally
1. What Problem Does Inheritance Solve?#
Imagine creating multiple users:
const user1 = {
name: "John",
greet() {
console.log("Hello");
},
};
const user2 = {
name: "Sarah",
greet() {
console.log("Hello");
},
};
Problem:
greet() is duplicated
Every object stores its own copy.
As objects grow, memory usage increases.
JavaScript solves this through:
Prototype Inheritance
2. What is a Prototype?#
Every JavaScript object has an internal reference to another object called its prototype.
Conceptually:
Object
↓
Prototype
When JavaScript cannot find a property on an object, it looks up the prototype chain.
Simple Example#
const animal = {
speak() {
console.log("Animal speaking");
},
};
const dog = Object.create(animal);
dog.speak();
Output:
Animal speaking
Why?
JavaScript searches:
dog
↓
animal
and finds:
speak();
inside animal.
3. Prototype Inheritance & Prototype Chain#
Prototype inheritance allows one object to inherit properties and methods from another object.
Example:
const animal = {
eat() {
console.log("Eating...");
},
};
const dog = Object.create(animal);
dog.eat();
Output:
Eating...
Even though:
dog.eat;
does not exist directly.
Understanding the Prototype Chain#
Consider:
const animal = {
eat() {
console.log("Eating");
},
};
const dog = Object.create(animal);
dog.name = "Tommy";
When JavaScript evaluates:
dog.eat();
it performs:
dog
↓
animal
↓
Object.prototype
↓
null
This lookup sequence is called the:
Prototype Chain
Visual Representation#
dog
↓
animal
↓
Object.prototype
↓
null
If a property is not found:
undefined
is returned.
Property Lookup Example#
const animal = {
species: "Animal",
};
const dog = Object.create(animal);
console.log(dog.species);
JavaScript searches:
dog
↓
animal
Finds:
species;
Output:
Animal
Property Shadowing#
Objects can override inherited properties.
Example:
const animal = {
type: "Animal",
};
const dog = Object.create(animal);
dog.type = "Dog";
console.log(dog.type);
Output:
Dog
JavaScript stops searching as soon as it finds the property.
4. Constructor Functions & proto vs. prototype#
Before ES6 classes, inheritance was commonly implemented using constructor functions.
function User(name) {
this.name = name;
}
Shared methods are added to the prototype:
User.prototype.greet = function () {
console.log(`Hello ${this.name}`);
};
Create instances:
const user1 = new User("John");
const user2 = new User("Sarah");
Now:
user1
↓
User.prototype
user2
↓
User.prototype
Both objects share the same method.
Why Is This Efficient?#
Bad approach:
function User(name) {
this.name = name;
this.greet = function () {
console.log("Hello");
};
}
Every instance gets a new function.
user1.greet
user2.greet
user3.greet
Three separate copies.
Better Approach#
User.prototype.greet = function () {
console.log("Hello");
};
Now:
One Function
Shared By All Instances
Much more memory efficient.
How new Works Internally#
When JavaScript executes:
const user = new User("John");
it roughly performs:
const obj = {};
obj.__proto__ = User.prototype;
User.call(obj, "John");
return obj;
Result:
obj
↓
User.prototype
This is how inheritance is established.
Prototype Chain with Constructor Functions#
function User() {}
const user = new User();
Chain:
user
↓
User.prototype
↓
Object.prototype
↓
null
Interview Question#
What is the Difference Between __proto__ and prototype?#
Many developers confuse these.
prototype
Exists on functions.
function User() {}
console.log(User.prototype);
Used when creating new objects.
__proto__
Exists on object instances.
const user = new User();
console.log(user.__proto__);
References the object's prototype.
Example#
function User() {}
const user = new User();
console.log(user.__proto__ === User.prototype);
Output:
true
Multi-Level Inheritance#
const livingThing = {
breathe() {
console.log("Breathing");
},
};
const animal = Object.create(livingThing);
animal.eat = function () {
console.log("Eating");
};
const dog = Object.create(animal);
Chain:
dog
↓
animal
↓
livingThing
↓
Object.prototype
↓
null
Now:
dog.breathe();
dog.eat();
Both work.
5. ES6 Classes Under the Hood#
Modern JavaScript:
class User {
greet() {
console.log("Hello");
}
}
Looks cleaner.
But internally JavaScript creates:
User.prototype.greet = function () {
console.log("Hello");
};
Classes are syntax sugar over prototypes.
Verify It Yourself#
class User {
greet() {}
}
console.log(typeof User.prototype.greet);
Output:
function
6. Object.create() & hasOwnProperty()#
A common interview topic.
const animal = {
eat() {
console.log("Eating");
},
};
const dog = Object.create(animal);
Result:
dog
↓
animal
No constructor function required.
hasOwnProperty()#
Used to determine whether a property belongs directly to an object.
const animal = {
type: "Animal",
};
const dog = Object.create(animal);
dog.name = "Tommy";
Check:
dog.hasOwnProperty("name");
Output:
true
Check:
dog.hasOwnProperty("type");
Output:
false
Because it comes from the prototype.
7. Common Interview Q&A#
How Does JavaScript Achieve Inheritance?#
Through prototype delegation.
Objects inherit properties and methods from their prototype chain.
What Happens If a Property Isn't Found?#
JavaScript searches:
Current Object
↓
Prototype
↓
Prototype's Prototype
↓
null
This process is called prototype chain lookup.
Are Classes and Prototypes Different?#
No.
Classes are built on top of prototypes.
Inheritance still happens through the prototype chain.
Why Use Prototype Methods?#
Because methods are shared across all instances.
This reduces memory usage.
What Does Object.create() Do?#
Creates a new object whose prototype is the provided object.
Senior-Level Interview Answer#
JavaScript uses prototype-based inheritance rather than classical inheritance. Every object has an internal reference to another object known as its prototype. When a property or method is accessed, JavaScript first searches the object itself and then walks up the prototype chain until it finds the property or reaches null. Constructor functions and ES6 classes both rely on this mechanism internally. Methods placed on a constructor's prototype are shared across all instances, making prototype inheritance memory efficient and fundamental to JavaScript's object-oriented model.
Common Interview Mistakes#
❌ "Classes create inheritance."
Correct:
Prototypes create inheritance.
Classes are syntax sugar.
❌ "prototype and __proto__ are the same."
Correct:
prototype → exists on functions
__proto__ → exists on objects
❌ "Methods are copied to every object."
Correct:
Methods are shared through the prototype chain.
Key Takeaways#
- Prototype Linkage: Every JavaScript object holds a link to a prototype object from which it inherits properties.
- Prototype Chain: Property lookup searches the object, then its prototype, ascending the chain until hitting
null. - Constructor Functions: Share methods efficiently by attaching them to the constructor's
prototypeobject. - Memory Optimization: Storing methods on prototypes rather than duplicating them inside constructor instances saves memory.
- ES6 Classes: Standard syntactic sugar built on top of prototype chains, not a new inheritance model.