Emmanuel Akinfulubi

Object-oriented JavaScript, from the beginning.

Fifteen lessons that take you from “what is an object” to designing your own classes. Every example runs on the page, so you never have to take a claim about the language on trust.

Where this is going

You are not expected to understand the code below yet. Run it anyway. By lesson 15 every line will be something you could have written, and you can come back here to check.

Everything in the course, running

// A class describes how to build something.
class Bus {
  #seatsLeft;                   // private: nothing outside can touch it
  static built = 0;             // belongs to the class, not to one object

  constructor(plate, seatsLeft) {
    this.plate = plate;         // public data, on this instance
    this.#seatsLeft = seatsLeft;
    Bus.built++;
  }

  get seatsLeft() { return this.#seatsLeft; }   // readable, not writable

  book(n) {                     // behaviour, shared by every bus
    if (n > this.#seatsLeft) throw new RangeError(`${this.plate}: only ${this.#seatsLeft} left`);
    this.#seatsLeft -= n;
    return this;                // returning this lets calls chain
  }

  describe() { return `${this.plate} has ${this.#seatsLeft} seats left`; }
}

// Inheritance: a more specific description, built on the general one.
class LuxuryBus extends Bus {
  constructor(plate, seatsLeft, extra) {
    super(plate, seatsLeft);    // build the Bus part first
    this.extra = extra;
  }

  describe() {                  // same name, different answer: polymorphism
    return super.describe() + `, with ${this.extra}`;
  }
}

const fleet = [
  new Bus('ABJ-772-KM', 6),
  new LuxuryBus('LAG-441-XA', 9, 'air conditioning'),
];

// One loop, two types, each answering in its own way.
for (const member of fleet) console.log(member.describe());

console.log('built so far:', Bus.built);
console.log('a LuxuryBus is also a Bus:', fleet[1] instanceof Bus);

fleet[1].book(3);
console.log(fleet[1].describe());

try { fleet[0].book(99); } catch (err) { console.log('refused:', err.message); }

Output


      

Part one — Objects

What an object is, what it can do, and the one keyword everything turns on.

  1. 01 What an Object Actually Is Make an object by hand and read values back out of it. 9 min
  2. 02 Properties and Methods Give an object behaviour, not just data. 11 min
  3. 03 The Word this Predict what this is in any call, and fix it when it is wrong. 15 min
  4. 04 Factory Functions Build many similar objects from one function. 10 min
  5. 05 Constructors and new Explain exactly what new does, step by step. 13 min

Part two — The machinery

Prototypes, class syntax, and where to keep state so it stays yours.

  1. 06 Prototypes and the Chain Above Trace a property lookup all the way up the chain. 16 min
  2. 07 class: the Same Thing, Less Typing Write a class with a constructor, fields and methods. 12 min
  3. 08 Encapsulation Hide internal state behind a deliberate public surface. 13 min
  4. 09 Getters and Setters Expose computed values and validate assignment. 11 min
  5. 10 Static Members Put counters, factories and constants where they belong. 10 min

Part three — Design

Reuse, substitution, and knowing which of these tools not to reach for.

  1. 11 Inheritance: extends and super Extend a class correctly, including its constructor. 15 min
  2. 12 Polymorphism Write code that handles many types through one interface. 12 min
  3. 13 Abstraction Design an interface that hides the machinery behind it. 11 min
  4. 14 Composition Over Inheritance Choose between "is a" and "has a", and refactor from one to the other. 14 min
  5. 15 SOLID and Four Real Patterns Name the smell, then name the fix. 18 min

Nothing marked done yet. Lesson 01 is a good place to start.

What object-oriented actually means

Four ideas carry the whole subject. JavaScript's answers to them are unusual enough that learning OOP from a Java or Python tutorial will actively mislead you.

Encapsulation

Keep data and the operations allowed on it together, and let the outside world touch only what you deliberately expose. A balance that can only change through deposit and withdraw cannot silently go negative.

Lessons 02, 04, 08, 09

Abstraction

Decide what the person using your object never needs to know. They ask for the total; they do not think about how it is stored.

Lessons 13, 14

Inheritance

Build a specific thing on top of a general one so shared behaviour is written once. The most powerful of the four and by a wide margin the most misused, which is why two lessons are spent on when to refuse it.

Lessons 06, 11, 14

Polymorphism

Many different objects answering the same request, each in its own way, so the calling code stops caring which one it has.

Lessons 12, 15

How to work through it

The order matters more here than in most courses, because lessons 04 to 07 are one continuous argument: factories, then constructors, then prototypes, then class. Read them in sequence and class arrives as an obvious shortcut. Skip to class first and it stays magic, which is where most working JavaScript developers are stuck.

  1. Read with this page in one window and your editor in the other.
  2. Run every example. When the output surprises you, change a line and run it again. That is the whole study method.
  3. Do the task at the foot of each lesson before moving on. It is short on purpose.
  4. After lesson 07 and again after 15, work through the drills, then build the project.

Everything else

What this is, honestly

A course written to be read offline. It has no account, no backend, no analytics and no network calls of any kind; the fonts are inlined into the stylesheet and the syntax highlighter is a few hundred lines in assets/js/highlight.js. Your progress and anything you type into an editable panel are kept in this browser's localStorage and nowhere else, so clearing site data clears them.

Code you type into a panel runs in your own browser, in a function scope with a shadowed console, always with "use strict" applied. That is what makes the examples honest. It also means an editable panel will run whatever you paste into it, so treat it the way you would treat your own devtools console.

Newsletter

New writing, when it lands.

Occasional notes on shipping software with AI agents. No schedule, no filler, unsubscribe in one click.