Skip to main content

OOP: Classes, Prototypes & Inheritance


Prototype Basics

Every object in JS has a prototype chain. Properties are looked up the chain until found or null.

const obj = { a: 1 };
Object.getPrototypeOf(obj); // Object.prototype
Object.getPrototypeOf(Object.prototype); // null (end of chain)

// Array prototype chain:
// [] → Array.prototype → Object.prototype → null
[].push === Array.prototype.push; // true

Constructor Functions (Pre-ES6)

function Animal(name, sound) {
this.name = name;
this.sound = sound;
}

// Methods on prototype (shared, not per-instance)
Animal.prototype.speak = function() {
return `${this.name} says ${this.sound}`;
};

const cat = new Animal("Cat", "meow");
cat.speak(); // "Cat says meow"

// What `new` does:
// 1. Creates empty object {}
// 2. Sets prototype to Animal.prototype
// 3. Calls Animal with this = new object
// 4. Returns the new object

ES6 Classes

class Animal {
#sound; // private field (ES2022)

constructor(name, sound) {
this.name = name;
this.#sound = sound;
}

// Instance method (on prototype, shared)
speak() {
return `${this.name} says ${this.#sound}`;
}

// Static method (on class itself, not instances)
static create(name, sound) {
return new Animal(name, sound);
}

// Getter
get info() {
return `${this.name} (${this.#sound})`;
}

// Setter
set sound(value) {
if (typeof value !== "string") throw new TypeError("Must be a string");
this.#sound = value;
}
}

const cat = new Animal("Cat", "meow");
cat.speak(); // "Cat says meow"
cat.info; // "Cat (meow)"
Animal.create("Dog", "woof"); // static method

Inheritance with extends

class Animal {
constructor(name) {
this.name = name;
}

speak() {
return `${this.name} makes a sound.`;
}
}

class Dog extends Animal {
constructor(name, breed) {
super(name); // MUST call super() before using this
this.breed = breed;
}

// Override parent method
speak() {
return `${this.name} barks!`;
}

// Call parent method
superSpeak() {
return super.speak();
}
}

const d = new Dog("Rex", "Labrador");
d.speak(); // "Rex barks!" (overridden)
d.superSpeak(); // "Rex makes a sound." (parent)
d.name; // "Rex" (inherited)

d instanceof Dog; // true
d instanceof Animal; // true

Private Fields and Methods (ES2022)

class Counter {
#count = 0; // private field
#max;

constructor(max = Infinity) {
this.#max = max;
}

#validate() { // private method
if (this.#count >= this.#max) throw new Error("Max reached");
}

increment() {
this.#validate();
this.#count++;
return this; // method chaining
}

get value() { return this.#count; }
}

const c = new Counter(3);
c.increment().increment();
c.value; // 2
c.#count; // SyntaxError: private field!

Static Methods and Fields

class MathUtils {
static PI = 3.14159; // static field

static add(a, b) { return a + b; }
static multiply(a, b) { return a * b; }
}

MathUtils.PI; // 3.14159
MathUtils.add(2, 3); // 5
// new MathUtils().add(2,3) — Error: not on instances

Mixins Pattern

JavaScript doesn't support multiple inheritance directly — use mixins.

const Serializable = (Base) => class extends Base {
serialize() { return JSON.stringify(this); }
static deserialize(json) { return JSON.parse(json); }
};

const Validatable = (Base) => class extends Base {
validate() { return Object.keys(this).length > 0; }
};

class User extends Serializable(Validatable(class {})) {
constructor(name) { super(); this.name = name; }
}

const user = new User("Reet");
user.validate(); // true
user.serialize(); // '{"name":"Reet"}'

MCQ — OOP

Q1: What does super() do in a constructor?

A) Creates the parent class B) Calls the parent class constructor ✅ C) Inherits all parent methods D) Returns the parent instance

Answer: B — Must be called before using this in a derived class constructor.

Q2: What is the prototype chain?

A) A linked list of classes B) A series of objects linked via __proto__ used for property lookup ✅ C) The order in which constructors are called D) The class hierarchy tree

Answer: B

Q3: Are class methods stored on the instance or the prototype?

A) The instance B) The prototype ✅ C) Both D) A separate method registry

Answer: B — Methods are shared via the prototype, reducing memory usage.

Q4: What is a private field in ES2022?

A) A field prefixed with _ (convention only) B) A field prefixed with # that is truly inaccessible outside the class ✅ C) A field defined with private keyword D) A field stored in WeakMap

Answer: B

Q5: Can a class extend multiple parent classes in JavaScript?

A) Yes B) No — only single inheritance, but mixins can simulate multiple ✅ C) Yes with class X extends A, B {}

Answer: B

Q6: What does instanceof check?

A) Whether objects have the same properties B) Whether a constructor's prototype appears anywhere in the object's prototype chain ✅ C) Whether the object was created with new

Answer: B