Understanding Prototypal Inheritance
JavaScript uses prototypal inheritance, not classical inheritance. Every object has an internal link to another object called its prototype. When you access a property that doesn't exist, JavaScript walks up the "prototype chain" to find it.
The Prototype Chain
const animal = {
eats: true,
walk() { return 'Walking...'; }
};
const dog = Object.create(animal);
dog.barks = true;
dog.bark = function() { return 'Woof!'; };
console.log(dog.barks); // true (own property)
console.log(dog.eats); // true (inherited from animal)
console.log(dog.walk()); // 'Walking...'
Constructor Functions
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
return `Hi, I'm ${this.name} and I'm ${this.age} years old.`;
};
const alice = new Person('Alice', 25);
console.log(alice.greet()); // "Hi, I'm Alice and I'm 25 years old."
console.log(alice.greet === new Person('Bob', 16).greet); // true (shared)
ES6 Classes (Syntactic Sugar)
class Animal {
constructor(name, sound) {
this.name = name;
this.sound = sound;
}
speak() { return `${this.name} says ${this.sound}!`; }
}
class Dog extends Animal {
constructor(name, breed) {
super(name, 'Woof');
this.breed = breed;
}
fetch(item) { return `${this.name} fetches the ${item}`; }
}
const rex = new Dog('Rex', 'German Shepherd');
console.log(rex.speak()); // "Rex says Woof!"
console.log(rex instanceof Dog); // true
console.log(rex instanceof Animal); // true
Polymorphism
class Shape {
area() { return 0; }
describe() { return `Area: ${this.area()}`; }
}
class Circle extends Shape {
constructor(r) { super(); this.r = r; }
area() { return Math.PI * this.r ** 2; }
}
class Rectangle extends Shape {
constructor(w, h) { super(); this.w = w; this.h = h; }
area() { return this.w * this.h; }
}
const shapes = [new Circle(5), new Rectangle(4, 6)];
shapes.forEach(s => console.log(s.describe()));
Key Takeaways
- Every object has a prototype (except
null) - Property lookup traverses the prototype chain
classis syntactic sugar over prototypes- Use
Object.create()for explicit prototype-based inheritance