Prototype Inheritance
π― JavaScript's Inheritance Model
JavaScript uses prototypal inheritance where objects inherit directly from other objects. This is more flexible than classical inheritance and enables patterns like mixins and composition.
Inheritance Patterns Comparison
Classical Inheritance
Parent β Child relationships
- Clear hierarchy
- Good for is-a relationships
- Can be rigid
Prototypal Inheritance
Object β Object delegation
- More flexible
- Dynamic inheritance
- Less boilerplate
Composition
Has-a relationships
- Most flexible
- No inheritance issues
- Easier to test
Example 1: Classical Inheritance Pattern
JavaScript Editor
π§ Inheritance Setup Steps
Step 1: Call Parent Constructor
function Child() {
// Pass current context to parent
Parent.call(this);
// Child-specific initialization
}Step 2: Set Up Prototype Chain
// Link prototypes Child.prototype = Object.create( Parent.prototype ); // Fix constructor reference Child.prototype.constructor = Child;
Step 3: Add Child Methods
Child.prototype.childMethod = function() {
// Child-specific logic
};Step 4: Override Parent Methods
Child.prototype.parentMethod = function() {
// Call parent version if needed
Parent.prototype.parentMethod.call(this);
// Child-specific logic
};Example 2: Multiple Levels of Inheritance
JavaScript Editor
β οΈ The Fragile Base Class Problem
Deep inheritance chains can create fragile code where changes to base classes break derived classes. This is why composition is often preferred over deep inheritance.
- Base class changes affect all derived classes
- Difficult to understand the full hierarchy
- Performance degrades with deep chains
- Tight coupling between classes
Example 3: Mixins and Composition vs Inheritance
JavaScript Editor
π Inheritance vs Composition
| Factor | Inheritance | Composition |
|---|---|---|
| Relationship | IS-A (Dog is an Animal) | HAS-A (Dog has eating behavior) |
| Flexibility | β Fixed at compile time | β Dynamic at runtime |
| Coupling | β Tight (depends on parent) | β Loose (independent) |
| Reusability | β οΈ Through hierarchy | β Through mixing |
| Testing | β Requires parent setup | β Independent testing |
| Use Case | Clear hierarchical domains | Behavior-based systems |
Example 4: Prototype Chain Optimization
JavaScript Editor
Exercise: Choose the Right Pattern
JavaScript Editor
π‘ Best Practices for JavaScript Inheritance
- Prefer composition over inheritance when possible
- Use ES6 classes for cleaner syntax (they still use prototypes)
- Keep inheritance chains shallow (max 2-3 levels)
- Use mixins for cross-cutting concerns
- Consider factory functions for complex object creation
- Avoid modifying built-in prototypes in production code
- Use
Object.create(null)for dictionary objects - Be mindful of performance with deep prototype chains
π― Interview Questions on Prototype Inheritance
- What's the difference between classical and prototypal inheritance?
- How would you implement multiple inheritance in JavaScript?
- What are the advantages of composition over inheritance?
- How do you properly set up inheritance in JavaScript?
- What's the fragile base class problem?
- How do ES6 classes differ from constructor functions?
- What are mixins and when would you use them?
- How does JavaScript's prototype chain affect performance?
- What's the difference between
Object.create()andnew? - How would you implement private properties in JavaScript classes?