Object-Oriented JavaScript
Static, private, and checks, Composition vs inheritance & mixins 🎯, SOLID in JS (pragmatic)
Classes are syntactic sugar over prototypes (Objects). Under the hood, methods live on Class.prototype.
class Animal {
static count = 0; // static field (on the class)
#energy = 100; // private field (truly private) 🟢
constructor(name) {
this.name = name; // public instance field
Animal.count++;
}
speak() { return `${this.name} speaks`; } // on prototype
get energy() { return this.#energy; } // getter
set energy(v) { this.#energy = Math.max(0, v); }
#recover() { this.#energy += 10; } // private method
static create(name) { return new Animal(name); } // static method
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // must call before using `this`
this.breed = breed;
}
speak() { return `${super.speak()} — woof`; } // override + super
}
const d = new Dog("Rex", "Lab");
d.speak(); // "Rex speaks — woof"
d instanceof Animal;// true
Animal.count; // 1
// d.#energy // ❌ SyntaxError — private, inaccessible outside
Static, private, and checks#
staticmembers belong to the class, not instances.#field/#method()are hard private — enforced by the engine (unlike_nameconvention).#x in obj🟢 (ES2022) is the brand check for private fields.
Composition vs inheritance & mixins 🎯#
Prefer composition ("has-a") over deep inheritance ("is-a"). Deep hierarchies are rigid and fragile.
// mixin — share behaviour without inheritance
const Serializable = (Base) => class extends Base {
toJSON() { return JSON.stringify({ ...this }); }
};
class User {}
class SerializableUser extends Serializable(User) {}
SOLID in JS (pragmatic)#
- Single Responsibility — a module/class does one thing.
- Open/Closed — extend behaviour without editing existing code (strategy pattern, plugins).
- Liskov — subtypes must be usable wherever the base is.
- Interface Segregation — small focused interfaces (in JS, small focused objects/functions).
- Dependency Inversion — depend on abstractions; inject dependencies rather than hard-coding them.
Interview Q&A#
Q1. Are JS classes "real" classes? What's underneath?
No — class is syntactic sugar over prototypes. Methods live on Class.prototype, and extends wires up the prototype chain. There's no separate class type system as in Java/C++.
Q2. #private vs _convention privacy — what's the difference and how is it enforced?
#field/#method() are hard private, enforced by the engine — accessing them from outside is a SyntaxError and they're invisible to reflection. _name is only a naming convention; nothing stops outside code from reading or writing it.
Q3. Composition vs inheritance — when to prefer each? Prefer composition ("has-a") for most cases: it stays flexible and avoids the rigidity of deep hierarchies. Reach for inheritance only for genuine "is-a" relationships that are shallow and stable; mixins let you share behaviour without a rigid chain.
Q4. What does super do and when must you call it?
super(...) invokes the parent constructor and super.method() calls the parent's method (enabling override + delegation). In a subclass constructor you must call super() before touching this, otherwise you get a ReferenceError.