JavaScript Classes

Blueprint for Objects:

  • Think of a class as a "blueprint" or a schematic. Just as an architect uses a single blueprint to build many identical houses, developers use classes to create multiple objects that share the same structure and behavior.
  • Introduced in ES6 (2015), the class syntax is actually "syntactic sugar" over JavaScript’s existing prototype-based inheritance. It doesn't change how JavaScript works under the hood, but it makes the code much cleaner and easier to reason about.
Developer Tip: Always name your classes using PascalCase (e.g., UserAccount, ProductList). This helps distinguish classes from standard variables and functions at a glance.

Constructor Method:

  • The constructor is a special, predefined method that runs automatically whenever you create a new instance of a class. It is primarily used to set initial values for the object's properties.
  • You can only have one constructor per class. If you don't define one, JavaScript will provide an empty, default constructor for you.
Common Mistake: Forgetting the this keyword inside the constructor. Without this.variableName, you are creating a local variable that disappears once the constructor finishes, rather than saving a property to the object.

Encapsulation:

  • Encapsulation is the practice of bundling data (properties) and the logic that operates on that data (methods) into a single unit.
  • This keeps your code organized and prevents different parts of your application from accidentally interfering with each other’s internal states.
Best Practice: Keep your methods focused. A class method should ideally do one thing well (e.g., updateEmail()) rather than trying to handle multiple unrelated tasks.

Example: Basic Class Declaration

class Rectangle {
  // The constructor initializes the object state
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  // A method to perform logic based on the internal properties
  calculateArea() {
    return this.width * this.height;
  }
}

// Creating an 'instance' of the class
const rect = new Rectangle(5, 10);
console.log(rect.calculateArea()); // Output: 50
Watch Out: Unlike standard function declarations, classes are not hoisted. You must define your class before you try to use it with the new keyword, or you will get a ReferenceError.

Inheritance:

  • Inheritance allows you to create a "Child" class that takes all the functionality of a "Parent" class, then adds or overrides features. This follows the DRY (Don't Repeat Yourself) principle.
  • The extends keyword is used to link the classes, and the super() function is used to pass data up to the parent's constructor.

Example: Inheritance

class Square extends Rectangle {
  constructor(side) {
    // super() calls the Rectangle constructor with width and height
    super(side, side); 
  }
  
  // You can also add new methods specific to Square
  getPerimeter() {
    return this.width * 4;
  }
}

const square = new Square(5);
console.log(square.calculateArea()); // Output: 25 (inherited from Rectangle)
console.log(square.getPerimeter());   // Output: 20
Watch Out: If you define a constructor in a subclass, you must call super() before you can use the this keyword. If you don't, JavaScript will throw a ReferenceError.

Static Methods:

  • Static methods are defined on the class itself, not on the individual objects (instances) created from the class.
  • These are perfect for "utility" functions tasks that relate to the concept of the class but don't require any specific data from a particular instance.

Example: Static Method

class MathUtils {
  // This method belongs to the class MathUtils
  static add(x, y) {
    return x + y;
  }
}

// You call it directly on the Class name, not an instance
console.log(MathUtils.add(3, 5)); // Output: 8

// This would fail:
// const myMath = new MathUtils();
// myMath.add(3, 5); // Error: myMath.add is not a function

 

Key Points

  • Modern Syntax: JavaScript classes offer a cleaner, more standardized way to implement Object-Oriented Programming (OOP) patterns.
  • Maintenance: By grouping related data and logic, classes make your codebase easier to debug and scale as it grows.
  • Real-World Usage: Classes are widely used in modern frameworks like React (for Class Components) and NestJS, as well as in backend development for modeling database entities.
  • Structure: They enforce a specific structure (constructor, methods, properties), which makes your code more predictable for other developers on your team.
Best Practice: Use classes when you need to create multiple objects with shared behavior. If you only need a single object to store some settings, a simple const config = { ... } object literal is often better and more lightweight.