All topics
Objectsintermediate

ES6 Classes and Inheritance

The class syntax as syntactic sugar over prototype-based inheritance, including extends, super, and static members.

class is syntax over prototypes. It creates the same structure the constructor-function pattern did, with clearer syntax and a few real differences.

ES6 classes are like a nicer, pre-printed form for something you could always do with a blank sheet of paper (constructor functions and manual prototype linking) — the form is easier to fill out correctly, but it produces the exact same filing structure underneath.

Key Concepts

1
    class Animal {
      constructor(name) { this.name = name; }
      speak() { return `${this.name} makes a noise`; }
      static create(n) { return new Animal(n); }
      get label() { return `Animal: ${this.name}`; }
    }
${this.name} makes a noiseAnimal: ${this.name}
2
    class Dog extends Animal {
      constructor(name, breed) {
        super(name);              // must come first
        this.breed = breed;
      }
      speak() { return `${super.speak()} -- a bark`; }
    }
${super.speak()} -- a bark
3
super(...) before this. Using this in a derived constructor before calling super throws — the instance does not exist until the parent constructor has run.
super(...)thissuper
4
Methods go on the prototype, static members on the constructor itself. So speak is shared by every instance, exactly as in the prototype form.
speak
5
What classes add beyond syntax.
    they are not hoisted usably -- TDZ, like let
    the body is always strict mode
    calling one without new throws
    methods are non-enumerable, so for...in skips them
6
That last one is an improvement: a prototype method assigned the old way showed up in for...in.
for...in
7
Private fields are real.
    class Account {
      #balance = 0;
      deposit(n) { this.#balance += n; }
      get balance() { return this.#balance; }
    }
8
    acc.#balance      // SyntaxError, from outside the class
9
Enforced by the engine, not by an underscore convention.
10
Fields as arrow functions bind this.
    class Button {
      handleClick = () => { this.count++; };   // safe to pass around
      handleOther() { this.count++; }          // loses this if extracted
    }
this
11
Which is why React class components used the first form for handlers.
12
instanceof works through the chain, and so does extends from built-ins:
instanceofextends
13
    class MyArray extends Array {}
14
The judgement. Classes suit things with identity and state that genuinely vary by type. For a bag of functions, a module of exported functions is simpler — and deep hierarchies are the thing composition exists to avoid.
15
What the interviewer is probing.1. "Are classes just syntactic sugar?" Probing: the nuance. Stalls: "Yes, entirely." *Moves up:* mostly, but not exactly — class bodies are strict mode, methods are non-enumerable, and calling one without new throws.
16
2. "Why must super() come before this in a constructor?" Probing: initialisation order. Stalls: "Convention." Moves up: this does not exist until the parent constructor has run, so touching it earlier throws ReferenceError.
17
3. "What does static mean on a class?" Probing: the placement. Stalls: "It is shared." Moves up: the member is on the constructor rather than instances, so it is reached through the class name.
18
4. "How do private fields differ from a naming convention?" Probing: real encapsulation. Stalls: "They are the same." Moves up: a # field is genuinely inaccessible from outside — a SyntaxError, not a convention — and is not visible to reflection or JSON.