Jan 28, 2026 • 4 min read

classes

What I learned, what I’m still figuring out, and where I might go next.


classes

Classes in JavaScript are a template for creating objects. As we learned, unlike many other languages, it’s easy to create JavaScript objects without classes, but that doesn’t mean classes aren’t useful.

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

const user = new User("Lane", 100);
  • The class declaration creates a new class
  • The constructor method is a special method that’s called when a new instance of the class (object) is created
  • The new keyword calls the constructor method and creates a new instance of the class

Private Properties

By default, all properties of a class are public, meaning they can be accessed and modified from outside the class. Here’s an example:

class Movie {
  constructor(title, rating) {
    this.title = title;
    this.rating = rating;
  }
}

const matrixMovie = new Movie("The Matrix", 9.5);
console.log(matrixMovie.title);
// The Matrix
matrixMovie.title = "The Matrix Reloaded";
console.log(matrixMovie.title);
// The Matrix Reloaded

Maybe we don’t want our title to be able to be changed anywhere in our code. We can make it private by prefixing it with a hash # and declaring it at the top of the class:

class Movie {
  #title;
  constructor(title, rating) {
    this.#title = title;
    this.rating = rating;
  }
}

const matrixMovie = new Movie("The Matrix", 9.5);
console.log(matrixMovie.#title);
// Uncaught SyntaxError: Private field '#title' must be declared in an enclosing class

Private properties can still be used from within the class:

class Movie {
  #title;
  constructor(title, rating) {
    this.#title = title;
    this.rating = rating;
  }

  getTitleAllCaps() {
    const allCaps = this.#title.toUpperCase();
    return allCaps;
  }
}

const matrixMovie = new Movie("The Matrix", 9.5);
console.log(matrixMovie.getTitleAllCaps());
// THE MATRIX

Static Methods

static method or property is bound to the class itself, not the instance of the class (an object). In this example, we create two instances of the User class:

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

const lane = new User("Lane", 30);
const allan = new User("Allan", 30);
console.log(lane.name); // Lane
console.log(allan.name); // Allan

In JavaScript, a class is just an object template, so when we create a static method or property the object instances can’t access it. So, static members are often used for utility functions for the class itself.

class User {
  static numUsers = 0;

  constructor(name, age) {
    this.name = name;
    this.age = age;
    User.numUsers++;
  }

  static getNumUsers() {
    return User.numUsers;
  }
}

const lane = new User("Lane", 30);
console.log(User.getNumUsers()); // 1
const allan = new User("Allan", 30);
console.log(User.getNumUsers()); // 2

// This doesn't work because its not a method on the object
console.log(lane.getNumUsers());
// TypeError: lane.getNumUsers is not a function
//    at main.js:20:18

Getters and Setters

In JavaScript classes, getters and setters let us define special methods for getting and setting the values of properties. They look like regular methods but are accessed like properties. Here’s an example using the get keyword:

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

  get name() {
    return this._name.toUpperCase();
  }
}

const lane = new User("Lane", 30);
console.log(lane.name); // LANE

Notice that we’ve renamed this.name to this._name in our constructor to avoid a name collision with the getter itself.

A setter lets us control what happens when a property is changed. For example, we could validate a user’s age to make sure it’s not negative:

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

  get age() {
    return this._age;
  }

  set age(value) {
    if (value < 0) {
      throw new Error("Age can't be negative.");
    }
    this._age = value;
  }
}

const lane = new User("Lane", 29);
lane.age = -5; // "Age can't be negative."
console.log(lane.age); // 29

Super

The super keyword allows us to call methods on an object’s parent. It’s often used to call a parent’s constructor method when the child object has its own.

class Titan {
  constructor(name) {
    this.name = name;
  }

  toString() {
    return `Titan - Name: ${this.name}`;
  }
}

class BeastTitan extends Titan {
  constructor(name, power) {
    // call the parent's constructor
    super(name);
    this.power = power;
  }

  toString() {
    // call the parent's `toString` method
    return `${super.toString()}, Power: ${this.power}`;
  }
}

const beast = new BeastTitan("Zeke", 9000);
console.log(beast.toString());
// Titan - Name: Zeke, Power: 9000

Still Curious About