Classes

Blueprints for creating objects. Syntactic sugar over prototypes.

Class Basics

A template for creating objects with shared structure.

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  greet() {
    return `Hi, I'm ${this.name}`;
  }
}

const alice = new User("Alice", "alice@test.com");
alice.greet(); // "Hi, I'm Alice"
alice.name;    // "Alice"

💡 Classes are syntactic sugar over prototypes. Under the hood, typeof User is "function" and methods live on User.prototype.

Constructor

Runs automatically when you create a new instance.

class Product {
  constructor(name, price) {
    // Initialize instance properties:
    this.name = name;
    this.price = price;
    this.createdAt = new Date();
  }
}

const laptop = new Product("MacBook", 2499);
laptop.name;      // "MacBook"
laptop.price;     // 2499
laptop.createdAt; // Date object

// Without 'new' → TypeError:
// Product("MacBook", 2499); // Error!

Instance properties

Set in constructor with this.x = value

Each instance gets its own copy

Prototype methods

Defined in class body

Shared between all instances

Methods

Functions that belong to the class. Includes getters and setters.

class Circle {
  constructor(radius) {
    this.radius = radius;
  }

  // Regular method:
  area() {
    return Math.PI * this.radius ** 2;
  }

  // Getter (accessed like a property):
  get diameter() {
    return this.radius * 2;
  }

  // Setter (assigned like a property):
  set diameter(d) {
    this.radius = d / 2;
  }
}

const c = new Circle(5);
c.area();     // 78.54 (method call)
c.diameter;   // 10 (getter — no parentheses)
c.diameter = 20; // setter
c.radius;     // 10

Static Members

Belong to the class itself, not instances.

class MathUtils {
  static PI = 3.14159;

  static circleArea(radius) {
    return this.PI * radius ** 2;
  }

  static max(...nums) {
    return Math.max(...nums);
  }
}

// Called on the CLASS:
MathUtils.PI;             // 3.14159
MathUtils.circleArea(5);  // 78.54
MathUtils.max(1, 5, 3);   // 5

// NOT on instances:
const m = new MathUtils();
m.PI;            // undefined
m.circleArea;    // undefined

Use static for: utility functions, factory methods, constants, and singletons.

Private Fields

Truly private with # prefix. Not accessible outside the class.

class BankAccount {
  #balance = 0;       // private field
  #owner;             // private field

  constructor(owner, initial = 0) {
    this.#owner = owner;
    this.#balance = initial;
  }

  deposit(amount) {
    if (amount <= 0) throw new Error("Invalid amount");
    this.#balance += amount;
  }

  get balance() {
    return this.#balance;
  }

  // Private method:
  #log(action) {
    console.log(`[${this.#owner}] ${action}`);
  }
}

const acc = new BankAccount("Alice", 100);
acc.deposit(50);
acc.balance;    // 150 (via getter)
acc.#balance;   // SyntaxError! Truly private
acc.#log;       // SyntaxError!

FAQ

Common questions about classes.