Prototypes & Prototypal Inheritance
How objects inherit from other objects through a live chain of links -- the real model under everything.
Object.create(proto)
Object.getPrototypeOf(obj)
obj.hasOwnProperty(key)JavaScript has no classes at its core -- it has objects linked to other objects. Every object has a hidden link, its [[Prototype]], to another object. Read a property that is missing and the engine walks up this prototype chain until it finds it or hits null.
const animal = { breathes: true };
const dog = Object.create(animal); // dog's prototype IS animal
dog.barks = true;
console.log(dog.breathes); // true -- found one link upWhere methods really live
When you call arr.map(), map is not on your array -- it is on Array.prototype, one link up, shared by every array. That sharing is why prototypes exist: one copy of each method, not one per instance.
Inspecting and setting
Object.getPrototypeOf(obj)-- read the link.Object.create(proto)-- make an object with a chosen prototype.obj.hasOwnProperty(k)-- is the property the object's own, or inherited?
Example
When to use it
- Add a reusable method to all instances of a custom class by attaching it to the prototype once.
- Inspect the prototype chain of an unfamiliar object in the console to understand what methods it inherits.
- Implement prototype-based inheritance without ES6 class syntax to understand how classes work under the hood.
More examples
Add method to prototype
Attaches speak to Animal.prototype so every Animal instance inherits it without re-creating the function.
function Animal(name) { this.name = name; }
Animal.prototype.speak = function () {
return this.name + " makes a sound.";
};
const dog = new Animal("Rex");
console.log(dog.speak()); // "Rex makes a sound."Prototype chain lookup
Shows the chain: array instance -> Array.prototype -> Object.prototype -> null.
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
console.log(Object.getPrototypeOf(Array.prototype) === Object.prototype); // truePrototype-based inheritance
Sets up prototype-based inheritance so Car instances can call methods from Vehicle.prototype.
function Vehicle(type) { this.type = type; }
Vehicle.prototype.describe = function () { return "I am a " + this.type; };
function Car(brand) {
Vehicle.call(this, "car");
this.brand = brand;
}
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car;
const c = new Car("Toyota");
console.log(c.describe()); // "I am a car"
Discussion