Skip to content
Laviyx Learn

Try

JavaScript course menu

JavaScript Classes: Constructors, Methods, Getters, Static and Private Fields

Learn JavaScript classes: defining a class, the constructor, instance properties and methods, class fields, getters and setters, static methods and properties, private #fields and methods, instanceof, and when to use classes.

Advanced10 min readUpdated
On this page

A class is a blueprint for creating objects that share the same structure and behaviour. If your program has many users, products or bank accounts, a class describes them once, and you create as many instances as you need.

Defining a class#

JavaScript
class Student {
  constructor(name, course) {
    this.name = name;
    this.course = course;
    this.completed = 0;
  }

  completeLesson() {
    this.completed++;
    return this;
  }

  describe() {
    return `${this.name} has completed ${this.completed} ${this.course} lessons`;
  }
}

const asha = new Student("Asha", "JavaScript");
const ravi = new Student("Ravi", "CSS");

asha.completeLesson().completeLesson();
ravi.completeLesson();

console.log(asha.describe());
console.log(ravi.describe());
console.log(asha instanceof Student);
Output
Asha has completed 2 JavaScript lessons
Ravi has completed 1 CSS lessons
true
  • class Student { ... } defines the class. Class names use PascalCase.
  • constructor runs when you call new Student(...); it sets up the new object's properties through this.
  • Methods such as describe() are shared by every instance.
  • new creates the instance. Calling a class without new is an error.
  • Returning this from a method allows chaining, as in asha.completeLesson().completeLesson().

Class fields#

Properties can be declared directly in the class body, which makes the shape of the object easy to see:

JavaScript
class Cart {
  items = [];
  currency = "₹";

  add(name, price) {
    this.items.push({ name, price });
  }

  total() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
}

const cart = new Cart();
cart.add("Pen", 20);
cart.add("Notebook", 60);
console.log(`${cart.currency}${cart.total()}`);
Output
₹80

Each instance gets its own items array.

Getters and setters#

A getter is a method you read like a property; a setter runs when the property is assigned, which is useful for validation:

JavaScript
class Temperature {
  #celsius = 0;

  get fahrenheit() {
    return this.#celsius * 9 / 5 + 32;
  }

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

  set celsius(value) {
    if (value < -273.15) throw new RangeError("Below absolute zero");
    this.#celsius = value;
  }
}

const t = new Temperature();
t.celsius = 30;
console.log(t.celsius, t.fahrenheit);

try {
  t.celsius = -500;
} catch (error) {
  console.log(error.message);
}
Output
30 86
Below absolute zero

Private fields and methods#

Names starting with # are private: they can only be used inside the class. Code outside cannot read or change them, which protects the object's rules:

JavaScript
class BankAccount {
  #balance = 0;

  deposit(amount) {
    this.#validate(amount);
    this.#balance += amount;
  }

  withdraw(amount) {
    this.#validate(amount);
    if (amount > this.#balance) throw new Error("Insufficient funds");
    this.#balance -= amount;
  }

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

  #validate(amount) {
    if (amount <= 0) throw new RangeError("Amount must be positive");
  }
}

const account = new BankAccount();
account.deposit(500);
account.withdraw(200);
console.log(account.balance);
console.log(account.balanceTypo);
console.log(Object.keys(account));
Output
300
undefined
[]

Trying to write account.#balance outside the class is a syntax error, so it cannot even run. Private fields are truly hidden, unlike the old convention of naming "private" properties with an underscore.

Static members#

static methods and properties belong to the class itself, not to instances. They suit helpers and factory functions:

JavaScript
class Temperature {
  static fromFahrenheit(f) {
    return Math.round(((f - 32) * 5) / 9);
  }

  static ABSOLUTE_ZERO = -273.15;
}

console.log(Temperature.fromFahrenheit(98.6));
console.log(Temperature.ABSOLUTE_ZERO);
Output
37
-273.15

You call them on the class (Temperature.fromFahrenheit), not on an instance. Math.max and Number.isNaN are built-in static methods.

Classes are functions underneath#

JavaScript classes are a clearer syntax over the language's prototypes: methods live on Student.prototype and are shared by all instances. typeof Student is "function". The Prototypes lesson shows how this works.

When to use classes#

Classes are a good fit when you have many objects with the same behaviour and internal state to protect: shopping carts, game entities, custom errors (Error Handling), or when a library or framework expects them. For simple data, plain objects and functions are often enough. Both styles are common in JavaScript.

Practice#

Practice exercise

Create a Rectangle class with width and height, a getter area, a method scale(factor) that returns a new rectangle, and a static method square(size). Test them.

Show solution
JavaScript
class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

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

  scale(factor) {
    return new Rectangle(this.width * factor, this.height * factor);
  }

  static square(size) {
    return new Rectangle(size, size);
  }
}

const r = new Rectangle(3, 4);
console.log(r.area);
console.log(r.scale(2).area);
console.log(Rectangle.square(5).area);
console.log(r.area);
Output
12
48
25
12

scale returns a new rectangle, so r itself is unchanged.

Key takeaway#

Finished this lesson?