← Back to Chapters

JavaScript Classes

? JavaScript Classes

⚡ Quick Overview

JavaScript classes provide a structured, modern syntax to create objects and manage inheritance. They are essentially syntactic sugar over JavaScript’s prototype-based system, but they make object-oriented code easier to read, write, and maintain.

With classes you can:

  • Define blueprints for objects (like Person, Animal, User).
  • Reuse logic through inheritance using extends and super().
  • Encapsulate data with getters, setters, and private fields.
  • Add utility behavior via static methods that live on the class itself.

? Key Concepts

  • Class: A template for creating objects with shared structure and behavior.
  • Constructor: Special method that runs when you create an instance using new; used to initialize properties.
  • Instance: The actual object created from a class (e.g., const p = new Person()).
  • Methods: Functions defined inside a class; shared across all instances via the prototype.
  • Inheritance: Mechanism to create a new class that reuses and extends another class using extends.
  • Getters/Setters: Special methods that run when you read or write a property.
  • Private Fields: Truly private properties defined using #name, only accessible inside the class.
  • Static Methods: Methods called on the class itself, not on instances.

? Syntax and Theory

A basic class uses the class keyword followed by a name (by convention, starting with a capital letter). Inside, you typically define a constructor and some methods.

Even though it looks similar to classes in other languages (like Java or C#), JavaScript classes still use prototypes under the hood. The class syntax just makes it cleaner and less error-prone.

? Basic Class Example

Here’s a simple Person class with a constructor and a method:

? View Code Example – Basic Person Class
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}

const person1 = new Person("Alice", 30);
person1.greet(); // Hello, my name is Alice.

? Output / Explanation

  • new Person("Alice", 30) calls the constructor and creates an object with name and age.
  • greet() is defined once on the prototype and shared by all Person instances.
  • person1.greet() prints: Hello, my name is Alice. in the console.

? Inheritance with Classes

Classes can inherit from other classes using the extends keyword. The child class can override or add new methods. Use super() to call the parent constructor or methods.

? View Code Example – Animal and Dog
class Animal {
constructor(name) {
this.name = name;
}

speak() {
console.log(`${this.name} makes a sound.`);
}
}

class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}

const dog = new Dog("Buddy");
dog.speak(); // Buddy barks.

? Output / Explanation

  • Dog extends Animal means Dog inherits from Animal.
  • The Dog class overrides speak() to provide a more specific behavior.
  • dog.speak() calls the overridden method, so you get Buddy barks. in the console.

⚙️ Getters and Setters

Getters and setters let you run logic whenever a property is read or updated. It’s common to use an underscore prefix (like _name) for the internal property.

? View Code Example – Getters and Setters
class User {
constructor(name) {
this._name = name;
}

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

set name(newName) {
if (newName.length > 0) {
this._name = newName;
}
}
}

const user = new User("bob");
console.log(user.name); // BOB
user.name = "sam";
console.log(user.name); // SAM

? Output / Explanation

  • The get name() method is called when you read user.name.
  • The set name() method runs when you assign user.name = "sam".
  • Here, the getter always returns the name in uppercase for display.

? Private Fields

Private fields start with # and are only accessible inside the class. They are great for hiding internal details.

? View Code Example – Private Balance
class BankAccount {
#balance = 0;

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

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

const account = new BankAccount();
account.deposit(100);
console.log(account.getBalance()); // 100
// console.log(account.#balance); ❌ SyntaxError

? Output / Explanation

  • #balance cannot be accessed from outside the class; trying to do so is a syntax error.
  • Only methods inside the class (deposit, getBalance) can use #balance.
  • This helps enforce encapsulation and prevents accidental misuse.

? Static Methods

Static methods belong to the class itself, not to instances. They are often used for helper or utility functions.

? View Code Example – Static Utility Method
class MathUtils {
static square(x) {
return x * x;
}
}

console.log(MathUtils.square(4)); // 16

? Output / Explanation

  • You call the method as MathUtils.square(4), not on an instance.
  • Static methods are useful when logic does not depend on a particular object’s data.

? Use Cases / When to Use Classes

  • Modeling real-world entities: User, Product, Order, Car.
  • Creating reusable components in frameworks (e.g., class-based React components, services in Node.js).
  • Organizing related logic in games (e.g., Player, Enemy, Weapon).
  • Encapsulating complex logic and exposing a clean public API for others to use.

?️ Interactive Example

Click the button to create a Person instance and see the greeting message below.

? Console Simulation

Click the button to simulate person.greet() output.

? Tips and Best Practices

  • Use classes to keep related properties and methods grouped together.
  • Use inheritance for shared behavior, but avoid deep or complicated hierarchies.
  • Encapsulate sensitive data using private fields and getters/setters.
  • Use static methods for actions that don’t rely on instance properties.
  • Keep class names descriptive and start them with a capital letter (e.g., BankAccount).

? Try It Yourself

  • Create a Product class with a name and price and a method to display details.
  • Use a getter and setter to manage and format the product name.
  • Define a Book class that extends Product and adds an author property.
  • Add a private field to store a discount and use a method to apply it.
  • Create a static method in Product to compare prices of two products.