Object-Oriented Programming in JavaScript

Introduction

Object-oriented programming (OOP) organizes code around objects that combine data and behavior. Procedural code focuses on steps and functions. JavaScript supports both styles—and ES6 classes are syntactic sugar over prototypes. This chapter explains when OOP helps and how it fits the language you already use with objects and functions.

Prerequisites

Procedural vs Object-Oriented

Procedural — functions operate on separate data:

javascript
// Data and functions are separate
let balance = 100;
 
function deposit(amount) {
  balance += amount;
}
 
function withdraw(amount) {
  balance -= amount;
}
 
deposit(50);
withdraw(20);
console.log(balance);

Object-oriented — data and methods live together:

javascript
// Behavior bundled with state
const account = {
  balance: 100,
  deposit(amount) {
    this.balance += amount;
  },
  withdraw(amount) {
    this.balance -= amount;
  },
};
 
account.deposit(50);
account.withdraw(20);
console.log(account.balance);

Both are valid—choose clarity for the problem size.

Class and Object

  • Class — blueprint (defines fields and methods)
  • Object (instance) — one concrete thing built from that blueprint
javascript
// Class defines shape; new creates instances
class Dog {
  constructor(name) {
    this.name = name;
  }
 
  bark() {
    return `${this.name} says woof`;
  }
}
 
const ada = new Dog("Ada");
const lin = new Dog("Lin");
 
console.log(ada.bark());
console.log(lin.bark());

Why Use Classes

Use classes when you have:

  • Repeated structure — many users, orders, or nodes with the same fields
  • Shared behaviorsave(), validate(), render() on each instance
  • Inheritance — specialized types extend a base (see inheritance)

For one-off config blobs, a plain object literal is often enough.

Encapsulation (Grouping + Hiding)

Keep related state inside the object; expose only what callers need:

javascript
// Private field with # (modern JS)
class Counter {
  #value = 0;
 
  increment() {
    this.#value += 1;
  }
 
  read() {
    return this.#value;
  }
}
 
const c = new Counter();
c.increment();
console.log(c.read());

Closures (see closures) are another way to hide state without classes.

JavaScript Is Multi-Paradigm

You will mix:

  • Object literals and classes
  • Functions and higher-order methods
  • Modules and async APIs later in the course

Mini Example: Modeling a Task

javascript
// Task type with consistent interface
class Task {
  constructor(title, done = false) {
    this.title = title;
    this.done = done;
  }
 
  toggle() {
    this.done = !this.done;
  }
 
  label() {
    return this.done ? `[x] ${this.title}` : `[ ] ${this.title}`;
  }
}
 
const t = new Task("Ship feature");
console.log(t.label());
t.toggle();
console.log(t.label());

FAQ

Is JavaScript “really” OOP?

Yes—objects and prototypes are core; class is the familiar syntax on top.

Should I avoid classes in favor of only functions?

Many codebases use both—classes for entity models, pure functions for transforms.

Class vs factory function?

Factories return plain objects without new; classes help when you need inheritance and instanceof.

What comes next?

Classes in JavaScript—syntax, instances, and methods.