JavaScript Prototypes & Inheritance
JavaScript uses prototypal inheritance. Every object has a prototype object from which it inherits properties and methods.
Prototype Chain
// Constructor function
function Person(name, age) {
this.name = name;
this.age = age;
}
// Add method to prototype
Person.prototype.greet = function() {
console.log(`Hello, I'm ${this.name}`);
};
Person.prototype.getAge = function() {
return this.age;
};
const john = new Person('John', 30);
john.greet(); // 'Hello, I'm John'
// Prototype chain lookup
console.log(john.name); // Own property
console.log(john.greet); // From Person.prototype
console.log(john.toString); // From Object.prototype
// Check prototype
console.log(john.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null (end of chain)
// hasOwnProperty
console.log(john.hasOwnProperty('name')); // true
console.log(john.hasOwnProperty('greet')); // false (in prototype)
// instanceof
console.log(john instanceof Person); // true
console.log(john instanceof Object); // truePrototypal Inheritance
// Parent constructor
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log(`${this.name} is eating`);
};
// Child constructor
function Dog(name, breed) {
Animal.call(this, name); // Call parent constructor
this.breed = breed;
}
// Set up inheritance
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// Add child methods
Dog.prototype.bark = function() {
console.log(`${this.name} says woof!`);
};
const dog = new Dog('Buddy', 'Golden Retriever');
dog.eat(); // 'Buddy is eating' (inherited)
dog.bark(); // 'Buddy says woof!' (own)
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
// ES6 Classes (syntactic sugar over prototypes)
class AnimalES6 {
constructor(name) {
this.name = name;
}
eat() {
console.log(`${this.name} is eating`);
}
}
class DogES6 extends AnimalES6 {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
console.log(`${this.name} says woof!`);
}
}Object.create() and Object.setPrototypeOf()
// Object.create() - creates object with specific prototype
const personPrototype = {
greet() {
console.log(`Hello, I'm ${this.name}`);
}
};
const john = Object.create(personPrototype);
john.name = 'John';
john.greet(); // 'Hello, I'm John'
// Object.create with properties
const jane = Object.create(personPrototype, {
name: {
value: 'Jane',
writable: true,
enumerable: true
},
age: {
value: 28,
writable: true
}
});
// Object.setPrototypeOf() - change prototype (avoid in production)
const dog = { name: 'Buddy' };
Object.setPrototypeOf(dog, personPrototype);
dog.greet(); // 'Hello, I'm Buddy'
// Object.getPrototypeOf()
console.log(Object.getPrototypeOf(john) === personPrototype); // trueKeep your own version of these notes — editable, searchable, and organised by your stack.
Start free