100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

Prototypes and Prototypal Inheritance in JavaScript

The mechanism underlying every JavaScript object: how property lookups walk the prototype chain, and how `prototype`, `__proto__`, and `Object.getPrototypeOf` relate.

OOP in JavaScriptAdvanced10 min readJul 8, 2026
Analogies

1. Introduction

Prototypal inheritance is the mechanism that underlies all of JavaScript's object-oriented behavior, including classes. Every object has an internal link to another object called its prototype, and when a property or method is not found directly on an object, the JavaScript engine automatically looks it up the prototype chain until it finds it (or reaches null). Classes, extends, and even plain object literals all ultimately rely on this system.

🏏

Cricket analogy: Every player inherits fielding basics from the general "cricketer" prototype, and if a specific skill like bowling legspin isn't found on the individual player, the lookup walks up to the team's specialist coaching prototype until it finds it or reaches the end of the chain.

2. Syntax

javascript
function Vehicle(type) {
  this.type = type;
}

// add a shared method to every Vehicle instance's prototype
Vehicle.prototype.describe = function () {
  return `This is a ${this.type}`;
};

const car = new Vehicle("car");

Object.getPrototypeOf(car);        // reads an object's prototype
Object.setPrototypeOf(car, proto); // sets an object's prototype

3. Explanation

There are two related but distinct concepts that beginners often confuse: the prototype **property**, which exists only on functions/classes and points to the object that will become the prototype of instances created with new, and the internal [[Prototype]] link that every object has, accessible via Object.getPrototypeOf(obj) or the legacy accessor obj.__proto__. So car.__proto__ === Vehicle.prototype is true, but car.prototype is undefined — plain instances do not have their own prototype property.

🏏

Cricket analogy: The "Bowler" blueprint itself has a prototype property listing shared techniques, but an actual bowler created from it, like Bumrah, only has an internal link back to that blueprint (Bumrah.__proto__ === Bowler.prototype is true) — Bumrah himself has no prototype property of his own.

When class Bike extends Vehicle {} is declared, the engine sets Object.getPrototypeOf(Bike.prototype) === Vehicle.prototype, chaining the prototypes together so instances of Bike can find describe() even though Bike never defines it. Every plain object literal ({}) automatically has Object.prototype as its prototype, which is where methods like toString() and hasOwnProperty() ultimately come from.

🏏

Cricket analogy: When the "SpinBowler" role extends the general "Bowler" role, a spin bowler instance can still use the base appeal() method it never redefined, because the chain links back to Bowler.prototype — just like every plain scoresheet object automatically inherits toString() from Object.prototype.

obj.hasOwnProperty("describe") checks only the object's OWN properties, not inherited ones. So car.hasOwnProperty("describe") is false (it's inherited), while Vehicle.prototype.hasOwnProperty("describe") is true (it's defined directly there). This distinction is key to understanding where a property actually 'lives' in the chain.

4. Example

javascript
function Vehicle(type) {
  this.type = type;
}
Vehicle.prototype.describe = function () {
  return `This is a ${this.type}`;
};

const car = new Vehicle("car");
console.log(car.describe());
console.log(Object.getPrototypeOf(car) === Vehicle.prototype);
console.log(car.__proto__ === Vehicle.prototype);
console.log(car.hasOwnProperty("describe"));
console.log(Vehicle.prototype.hasOwnProperty("describe"));

class Bike extends Vehicle {}
const bike = new Bike("bike");
console.log(bike.describe());
console.log(Object.getPrototypeOf(Bike.prototype) === Vehicle.prototype);

const plainObj = { greet() { return "hi"; } };
console.log(Object.getPrototypeOf(plainObj) === Object.prototype);

5. Output

text
This is a car
true
true
false
true
This is a bike
true
true

6. Key Takeaways

  • Every object has an internal prototype link; property lookups walk this chain until found or null is reached.
  • Function.prototype is a property that exists only on functions/classes, distinct from an instance's [[Prototype]].
  • Object.getPrototypeOf(obj) is the standard way to read an object's prototype; __proto__ is a legacy accessor for the same thing.
  • hasOwnProperty() checks only an object's own properties, excluding inherited ones from the chain.
  • class ... extends is implemented by linking Derived.prototype's prototype to Base.prototype.

Practice what you learned

Was this page helpful?

Topics covered

#JavaScript#JavaScriptProgrammingStudyNotes#Programming#PrototypesAndPrototypalInheritanceInJavaScript#Prototypes#Prototypal#Inheritance#Syntax#OOP#StudyNotes#SkillVeris