JavaScript Prototypes
Prototypes are the foundation of JavaScript’s object system. Every object has a prototype, forming a chain that JavaScript uses to look up properties and methods. Understanding prototypes is key to mastering JavaScript inheritance.
What Are Prototypes?
Every JavaScript object has a hidden [[Prototype]] property that links to another object. This creates a prototype chain for property lookup.
let person = {
name: 'Alice',
greet() {
console.log(`Hello, I'm ${this.name}`);
}
};
console.log(person.name); // 'Alice' (own property)
console.log(person.toString); // function (inherited from Object.prototype)
The Prototype Chain
When you access a property, JavaScript:
- Checks the object itself
- If not found, checks the object’s prototype
- Continues up the chain until
Object.prototype - If still not found, returns
undefined
let animal = {
eats: true,
walk() {
console.log('Animal walks');
}
};
let dog = Object.create(animal); // dog.__proto__ = animal
dog.barks = true;
console.log(dog.eats); // true (from animal)
console.log(dog.barks); // true (own property)
dog.walk(); // 'Animal walks' (from animal)
Constructor Functions
Before ES6 classes, we used constructor functions:
function Person(name, age) {
this.name = name;
this.age = age;
}
// Add methods to prototype
Person.prototype.greet = function() {
console.log(`Hi, I'm ${this.name}`);
};
let person1 = new Person('Alice', 30);
let person2 = new Person('Bob', 25);
person1.greet(); // 'Hi, I'm Alice'
All instances share the same prototype methods, saving memory.
Accessing Prototypes
Use __proto__ or Object.getPrototypeOf():
let arr = [1, 2, 3];
console.log(arr.__proto__ === Array.prototype); // true
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
Setting Prototypes
Use Object.setPrototypeOf() or __proto__:
let animal = { eats: true };
let dog = { barks: true };
Object.setPrototypeOf(dog, animal);
// or dog.__proto__ = animal;
console.log(dog.eats); // true
Prototype Inheritance
Create inheritance chains:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
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;
Dog.prototype.speak = function() {
console.log(`${this.name} barks`);
};
let dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // 'Buddy barks'
Modern Inheritance
ES6 classes use prototypes under the hood:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks`);
}
}This compiles to prototype-based code.
Checking Property Ownership
Use hasOwnProperty() to check if a property is own or inherited:
let obj = { ownProp: 'value' };
obj.__proto__ = { inheritedProp: 'inherited' };
console.log(obj.ownProp); // 'value'
console.log(obj.inheritedProp); // 'inherited'
console.log(obj.hasOwnProperty('ownProp')); // true
console.log(obj.hasOwnProperty('inheritedProp')); // false
Prototype Methods
Common prototype methods:
Object.create(proto)- Create object with specific prototypeObject.getPrototypeOf(obj)- Get prototypeObject.setPrototypeOf(obj, proto)- Set prototypeobj.isPrototypeOf(instance)- Check if obj is in prototype chain
let parent = { value: 42 };
let child = Object.create(parent);
console.log(parent.isPrototypeOf(child)); // true
console.log(Object.getPrototypeOf(child) === parent); // true
Performance Considerations
Prototype lookups are fast, but deep chains can slow things down. Keep inheritance shallow.
Modifying prototypes affects all instances:
function Car(model) {
this.model = model;
}
let car1 = new Car('Toyota');
let car2 = new Car('Honda');
Car.prototype.drive = function() {
console.log(`${this.model} is driving`);
};
car1.drive(); // 'Toyota is driving'
car2.drive(); // 'Honda is driving'
Prototypes are the core of JavaScript’s object model. Classes are just syntax on top of prototypes.
For more on classes, see JavaScript classes.
The MDN Prototypes guide is excellent for deeper understanding.