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