Classes

A class is a blueprint for creating many objects with the same shape and behaviour. You define the properties each object gets and the methods they share, then create as many instances as you need with new.

Defining a class

JS class.js
class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  area() {
    return this.width * this.height;
  }

  describe() {
    return `${this.width}×${this.height} rectangle with area ${this.area()}`;
  }
}

const small = new Rectangle(2, 3);
const big = new Rectangle(10, 4);

console.log(small.describe());
console.log(big.area());
Output
2×3 rectangle with area 6
40
  • Class names use PascalCase by convention.
  • constructor runs automatically when you call new Rectangle(…). It sets up the new object's properties via this.
  • Methods are written without the function keyword and without commas between them. They're shared by every instance.

Class fields

Properties can be declared directly in the class body with initial values, which keeps the constructor short and makes the object's shape obvious at a glance:

JS fields.js
class Counter {
  count = 0;
  step = 1;

  increment() {
    this.count += this.step;
    return this;
  }
}

const c = new Counter();
c.increment().increment().increment();
console.log(c.count);
Output
3

Returning this from a method allows method chaining, as on the second-to-last line.

Getters and setters

JS accessors.js
class User {
  constructor(first, last) {
    this.first = first;
    this.last = last;
  }

  get fullName() {
    return `${this.first} ${this.last}`;
  }

  set fullName(value) {
    [this.first, this.last] = value.split(" ");
  }
}

const u = new User("Ada", "Byron");
console.log(u.fullName);
u.fullName = "Ada Lovelace";
console.log(u.last);
Output
Ada Byron
Lovelace

Static members

static properties and methods belong to the class itself rather than to instances. They're used for helpers, factories and shared configuration:

JS static.js
class Temperature {
  static unit = "°C";

  constructor(celsius) {
    this.celsius = celsius;
  }

  static fromFahrenheit(f) {
    return new Temperature((f - 32) * 5 / 9);
  }

  toString() {
    return `${this.celsius.toFixed(1)}${Temperature.unit}`;
  }
}

const t = Temperature.fromFahrenheit(98.6);
console.log(String(t));
console.log(typeof t.fromFahrenheit);
Output
37.0°C
undefined

Static methods are called on the class (Temperature.fromFahrenheit), not on instances. A method named toString controls how the object turns into a string.

Classes must be called with new

JS no-new.js
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}

const p = Point(1, 2);
Output
Uncaught TypeError: Class constructor Point cannot be invoked without 'new'

Unlike old constructor functions, classes refuse to run without new, catching a common mistake. Class declarations are also not usable before their line (like let), and their bodies always run in strict mode.

Methods and lost this

Class methods are ordinary functions, so they lose this when passed as callbacks. Defining a method as an arrow function field binds it to each instance:

JS bound.js
class Clicker {
  clicks = 0;

  handleClick = () => {
    this.clicks++;
    return this.clicks;
  };
}

const clicker = new Clicker();
const handler = clicker.handleClick;
handler();
console.log(handler());
Output
2

This pattern is common for event handlers. The trade-off is that each instance gets its own copy of the function instead of sharing one on the prototype.

When to use a class

Classes fit well when you have many objects with the same structure and behaviour that also hold state — shopping carts, game sprites, UI components, API clients. For simple data with no behaviour, a plain object is enough. For grouping a few related functions, a module (lesson 55) is often simpler.

Try it yourself

Try it yourself
Console output