*
Previous constructor function Prototypes & Inheritance Next

๐Ÿ“˜ ES6 Classes in JavaScript

ES6 Classes

ES6 (ECMAScript 2015) introduced class syntax to provide a cleaner and more familiar way for developers to create objects and handle inheritance. While they look like traditional classes from languages like Java or C++, they are actually "syntactic sugar" over JavaScript's existing prototype-based inheritance model.

๐Ÿงฑ ES6 Class Syntax

The core components of a class are the class keyword, a constructor() method, and instance methods.

// A simple class declaration
class Vehicle {
  // A special method for creating and initializing objects
  constructor(make, model) {
    this.make = make;
    this.model = model;
  }

  // A method that can be called on an instance of the class
  displayDetails() {
    console.log(`This is a ${this.make} ${this.model}.`);
  }
}

// Create new objects (instances) using the `new` keyword
const myCar = new Vehicle("Toyota", "Camry");
const myTruck = new Vehicle("Ford", "F-150");

myCar.displayDetails(); // Output: "This is a Toyota Camry."
myTruck.displayDetails(); // Output: "This is a Ford F-150."

๐Ÿงฌ Inheritance with extends and super

One of the most powerful features of ES6 classes is the ability to create subclasses that inherit from a parent class.

  • extends: The keyword used to create a subclass.
  • super(): A method used inside a subclass constructor to call the parent class's constructor and inherit its properties.
class Car extends Vehicle {
  constructor(make, model, year) {
    super(make, model); // Call the parent constructor
    this.year = year;
  }
  
  displayDetails() {
    // Override the parent method and add new behavior
    console.log(`This is a ${this.year} ${this.make} ${this.model}.`);
  }
}

const myNewCar = new Car("Honda", "Accord", 2025);
myNewCar.displayDetails(); // Output: "This is a 2025 Honda Accord."

โœ… Advantages

  • ๐Ÿงน Cleaner Syntax: The class and extends keywords provide a more intuitive and readable syntax compared to the older prototype-based inheritance.
  • ๐ŸŒ OOP Familiarity: Developers from other object-oriented languages can transition to JavaScript more easily.
  • ๐Ÿ”’ Encapsulation: Using features like private class fields (with the # prefix) allows for better data hiding and encapsulation.
  • ๐Ÿ› ๏ธ Improved Tooling: The structured nature of classes enables better static analysis, type checking, and support from IDEs and code editors.
  • ๐Ÿšซ Prevents Accidental Misuse: Calling an ES6 class constructor without the new keyword throws an error, preventing a common mistake found with older constructor functions.

โš ๏ธ Disadvantages

  • ๐Ÿฌ "Syntactic Sugar": Since classes are just a different syntax for the underlying prototype system, they can hide some of the core language mechanics, which may be confusing for newcomers.
  • ๐Ÿšซ No Multiple Inheritance: JavaScript classes do not natively support multiple inheritance, although workarounds like mixins can be used.
  • ๐Ÿ”ง Doesn't Change Core Behavior: Classes do not introduce a fundamental change to JavaScript's object model, so it is still important to understand prototypes for more advanced use cases.

๐Ÿ“Œ When to Use

  • ๐Ÿ†• Modern Applications: For any new project, using ES6 classes is the standard and recommended approach for object creation and inheritance.
  • ๐Ÿ—๏ธ Complex Object Models: When modeling real-world entities with complex relationships, ES6 classes provide a clear and organized way to structure your code.
  • ๐Ÿ“ฆ Framework Development: Many modern frameworks and libraries, especially in the front-end space (e.g., React components), rely heavily on class-based patterns.

๐Ÿšซ When Not to Use

  • ๐Ÿ”น Simple Objects: For simple, one-off objects that don't need a formal structure or inheritance, a simple object literal ({ key: "value" }) or a factory function is often simpler and more appropriate.
  • ๐Ÿ“œ Legacy Code: When working within an older codebase that uses constructor functions and prototypes, it is often best to stick to that pattern for consistency.
  • ๐Ÿงฉ Forcing OOP: Avoid using classes just for the sake of it. If a different pattern, such as functional composition, is a better fit for the problem at hand, don't force a class-based solution.

๐Ÿง  Best Practices and Precautions

  • ๐Ÿ”  Capitalize Class Names: Follow the standard convention of capitalizing the first letter of a class name (e.g., class Vehicle).
  • ๐Ÿ“ž Use super(): In a subclass constructor, always call super() before accessing or setting properties on this.
  • ๐Ÿ” Use Private Fields for Encapsulation: Use the # prefix for private fields to properly encapsulate data that should not be accessed from outside the class.
  • ๐Ÿงฎ Use static Methods for Utilities: Use the static keyword for helper methods that belong to the class itself rather than to an instance.
  • ๐Ÿ”— Bind this for Callbacks: When passing class methods as callbacks, remember that their this context will change. Use arrow functions or .bind() to ensure the correct context.

Constructor Function vs ES6 Class in JavaScript

๐Ÿ”ง Constructor Function

This is the traditional way to create objects before ES6 introduced the class keyword.

// Constructor function
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

// Adding a method using prototype
Car.prototype.drive = function() {
  console.log(`Driving the ${this.make} ${this.model}`);
};

// Creating instances
const car1 = new Car("Toyota", "Camry", 2024);
car1.drive();

โœจ ES6 Class

This is the modern, cleaner syntax introduced in ES6. It uses the same prototypal inheritance under the hood.

// ES6 class
class Car {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  drive() {
    console.log(`Driving the ${this.make} ${this.model}`);
  }
}

// Creating instances
const car2 = new Car("Honda", "Accord", 2025);
car2.drive();

โœ… Key Differences

  • Syntax: ES6 classes are more concise and readable.
  • Method Definition: Constructor functions require prototype for shared methods; classes define them directly inside the class body.
  • Error Handling: Classes throw errors if not called with new; constructor functions do not.
  • Inheritance: ES6 classes support extends and super() for inheritance.

๐Ÿ“Œ Best Practice

For modern development, prefer ES6 classes for better readability, maintainability, and built-in inheritance support.

Back to Index
Previous constructor function Prototypes & Inheritance Next
*
*