Prototypes & Prototypal Inheritance

📖 Concept

Every JavaScript object has a hidden internal property called [[Prototype]] (accessible via __proto__ or Object.getPrototypeOf()). When you access a property that doesn't exist on an object, JavaScript looks up the prototype chain.

Prototype chain: object → object's prototype → prototype's prototype → ... → Object.prototype → null

This is JavaScript's inheritance model — prototypal inheritance. Unlike classical inheritance (classes in Java/C++), objects inherit directly from other objects.

Constructor functions + .prototype = the traditional way to create "classes" before ES6.

🏠 Real-world analogy: Prototypes are like family traits. If you don't have blue eyes (own property), check if your parent does (prototype). If they don't, check grandparent. Keep going up the family tree.

💻 Code Example

codeTap to expand ⛶
1// Every object has a prototype
2const arr = [1, 2, 3];
3// arr → Array.prototype → Object.prototype → null
4console.log(arr.__proto__ === Array.prototype); // true
5console.log(arr.__proto__.__proto__ === Object.prototype); // true
6
7// Constructor functions (pre-ES6 classes)
8function Animal(name, sound) {
9 this.name = name;
10 this.sound = sound;
11}
12// Methods on prototype (shared across all instances — memory efficient!)
13Animal.prototype.speak = function() {
14 return `${this.name} says ${this.sound}`;
15};
16const dog = new Animal("Rex", "Woof");
17console.log(dog.speak()); // "Rex says Woof"
18console.log(dog.hasOwnProperty("name")); // true (own property)
19console.log(dog.hasOwnProperty("speak")); // false (inherited from prototype)
20
21// Prototypal inheritance
22function Dog(name) {
23 Animal.call(this, name, "Woof"); // Call parent constructor
24}
25Dog.prototype = Object.create(Animal.prototype); // Set up prototype chain
26Dog.prototype.constructor = Dog; // Fix constructor reference
27Dog.prototype.fetch = function() {
28 return `${this.name} fetches the ball!`;
29};
30const rex = new Dog("Rex");
31console.log(rex.speak()); // "Rex says Woof" (inherited)
32console.log(rex.fetch()); // "Rex fetches the ball!" (own)
33
34// Object.create — direct prototypal inheritance
35const personProto = {
36 greet() { return `Hi, I'm ${this.name}`; }
37};
38const alice = Object.create(personProto);
39alice.name = "Alice";
40console.log(alice.greet()); // "Hi, I'm Alice"
41
42// Checking the prototype chain
43console.log(rex instanceof Dog); // true
44console.log(rex instanceof Animal); // true
45console.log(rex instanceof Object); // true

🏋️ Practice Exercise

Mini Exercise:

  1. Create a constructor function Vehicle with a drive() method on its prototype
  2. Create Car that inherits from Vehicle and adds a honk() method
  3. Verify the prototype chain using instanceof and Object.getPrototypeOf()
  4. Add a method to Array.prototype (then understand why this is dangerous)

⚠️ Common Mistakes

  • Adding methods directly to instances instead of the prototype — wastes memory for each instance

  • Modifying Object.prototype or Array.prototype — affects ALL objects/arrays globally!

  • Forgetting to set constructor after Dog.prototype = Object.create(Animal.prototype)

  • Confusing __proto__ (instance's link to its prototype) with .prototype (constructor's blueprint for instances)

  • Using for...in iterates over inherited properties — always check hasOwnProperty() or use Object.hasOwn()

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Prototypes & Prototypal Inheritance. Login to unlock this feature.