RoadmapDay 7 / 80
JavaScript CoreMonth 1 · Week 2

Day 7: Prototypes, Prototypal Inheritance & Class Transpilation

See JS classes for what they really are — sugar over prototype chains — so inheritance bugs and `instanceof` checks stop being mysterious.

Mark this day complete

Study

Concepts

Every object has a hidden link: [[Prototype]]

Objects in JS inherit through a chain of internal links (`[[Prototype]]`, exposed as `Object.getPrototypeOf(obj)` or the legacy `__proto__`). Reading a property that is not found on the object itself makes the engine walk this chain upward, checking each prototype in turn, until it finds the property or reaches `null`.

Functions have a special `.prototype` property (only on the function object, not on instances) that becomes the `[[Prototype]]` of every object created with `new Fn()`. That is the entire mechanism behind constructor-based inheritance.

class is syntax, not a new inheritance model

A `class` declaration desugars to: a constructor function, methods attached to `ClassName.prototype` (non-enumerable), and `extends` wiring up both the prototype chain (`Sub.prototype.__proto__ = Super.prototype`) and a static chain (`Sub.__proto__ = Super`) so static methods inherit too. `super()` inside a subclass constructor calls the parent constructor with the correct `this`.

The main real differences from old-style prototype code: class bodies run in strict mode, methods are non-enumerable by default, and a class cannot be called without `new` (throws a TypeError) — none of that is possible to fully replicate with plain functions, but the *lookup mechanism* is identical.

See It

Visualizations

Visualization

Prototype chain for an Employee instance

Property lookup walks up until found or hits null.

null
Object.prototype { toString, hasOwnProperty, ... }
Person.prototype { introduce() }
Employee.prototype { work() }
employee1 { name, role } ← lookup starts here

Build It

Code Examples

Pre-ES6: constructor functions + prototype (what class desugars to)

js
function Person(name) {
  this.name = name;
}
Person.prototype.introduce = function () {
  return `I am ${this.name}`;
};

function Employee(name, role) {
  Person.call(this, name); // "super()" equivalent
  this.role = role;
}
Employee.prototype = Object.create(Person.prototype); // wire the chain
Employee.prototype.constructor = Employee;
Employee.prototype.work = function () {
  return `${this.introduce()}, working as ${this.role}`;
};

const emp = new Employee('Ali', 'Engineer');
console.log(emp.work());               // "I am Ali, working as Engineer"
console.log(emp instanceof Person);     // true — walks the chain

The equivalent modern class

js
class Person {
  constructor(name) {
    this.name = name;
  }
  introduce() {
    return `I am ${this.name}`;
  }
}

class Employee extends Person {
  constructor(name, role) {
    super(name); // calls Person's constructor with the right 'this'
    this.role = role;
  }
  work() {
    return `${this.introduce()}, working as ${this.role}`;
  }
}

const emp = new Employee('Ali', 'Engineer');
console.log(Object.getPrototypeOf(emp) === Employee.prototype); // true
console.log(Object.getPrototypeOf(Employee.prototype) === Person.prototype); // true

Remember

Key Takeaways

  • Property lookup walks [[Prototype]] links upward until found or null — this IS "inheritance" in JS.
  • A function's .prototype becomes new instances' [[Prototype]] when called with new.
  • class is sugar: methods land on ClassName.prototype, extends wires the prototype AND static chains.
  • super() in a subclass constructor is literally ParentConstructor.call(this, ...args) under the hood.
  • instanceof checks whether a prototype appears anywhere in the chain — not the object's "type".

Do It

Practice

  1. 1Build a 3-level prototype chain (Animal → Dog → Puppy) without using class, only functions and Object.create.
  2. 2Add a method to Object.prototype and prove every object in your program suddenly has it — then explain why this is dangerous in real code.
  3. 3Use Object.getPrototypeOf repeatedly on a class instance to manually print its full chain up to null.