ReviseAlgo Logo

OOP in JavaScript

Abstract Patterns (Simulating Abstract Classes)

Master abstract classes patterns in JavaScript. Learn to enforce constructor checks, simulate abstract methods, and restrict class instantiations.

Last Updated: July 15, 2026 10 min read

1. Introduction

Some Object-Oriented languages support Abstract Classes, which are classes that cannot be instantiated directly and are meant to be extended by subclasses. JavaScript does not support abstract classes natively, but you can simulate them using constructor validation checks.

2. Why It Matters

When building large frameworks (like a database query interface or a rendering engine), you may want to define a base blueprint class that subclasses must inherit from. Simulating abstract classes ensures that developers don't instantiate the base class directly and guarantees that subclasses implement required methods.

3. Real-World Analogy

Think of a Government House Blueprint Office:

  • Standard Class (Ready-made model home): A builder offers a standard house layout. You can buy and build this exact home immediately.
  • Abstract Class (Building Zone Regulations): The building department defines a set of regulations: "Every house must have a foundation, an entry door, and a custom facade." You cannot buy or live in the regulations list itself (abstract class instantiation block). You must build a specific house (subclass) that complies with the regulations (inherits and implements abstract methods) before you can move in.

4. Simulating Abstract Classes

You can block direct instantiation of a class by checking the value of new.target inside the constructor. new.target points to the constructor that was invoked by the new keyword:

5. Subclass Implementation

Subclasses can inherit from the simulated abstract class, but they must implement the abstract methods to prevent errors:

6. Practical Example

This script demonstrates enforcing method implementation checks inside the base constructor:

7. Common Mistakes

  • Forgetting to call super() in the subclass: If you write a constructor in the subclass, you must call super() to run the parent constructor checks. Omitting super() throws a ReferenceError.

8. Quick Quiz

Q1: Which meta-property points to the constructor that was invoked by the 'new' keyword inside a class constructor?

A) new.target

B) this.constructor

Answer: A — new.target points to the constructor that was invoked, allowing you to detect if a base class is being instantiated directly.

9. Scenario-Based Challenge

The Encapsulated Payment Gateway Interface:

You want to write a payment system with an abstract base class: PaymentGateway. This class should enforce that all subclasses implement a processPayment(amount) method. Write this base class using new.target and method validation checks.

10. Debugging Exercise

Explain why this subclass instantiation crashes immediately, and how to fix it:

class AbstractConfig {
  constructor() {
    if (typeof this.load !== 'function') {
      throw new TypeError('Must implement load() method');
    }
  }
}

class SystemConfig extends AbstractConfig { // Bug: class defines load inside a field initialisation hook? load = function() { return 'loaded'; }; }

const config = new SystemConfig(); // throws TypeError: Must implement load() method! Why?

View Solution

Diagnosis: Class fields are initialized after the parent constructor (super()) runs. During the execution of AbstractConfig's constructor, the subclass property load has not been assigned yet, causing the validation check to fail.

Fix: Declare the method as a standard class method so it is defined on the prototype chain before the constructor runs, or assign the property in the subclass constructor:

class SystemConfig extends AbstractConfig {
  // Correct method definition (saved on prototype)
  load() {
    return 'loaded';
  }
}

11. Interview Questions

🟢 Q1: Explain how new.target can be used to simulate abstract classes in JavaScript.

Answer: new.target is a meta-property that points to the constructor function that was invoked by the new keyword.
Detecting Base Instantiation: If a base class is instantiated directly (e.g. new Base()), new.target points to the base class constructor.
Detecting Subclass Instantiation: If a subclass is instantiated (e.g. new Subclass()), new.target points to the subclass constructor.
By checking if (new.target === BaseClass) inside the base constructor, you can throw an error to block direct instantiation of the base class while still allowing subclasses to call super(), simulating an abstract class.

12. Production Considerations

  • Use TypeScript: If your project uses TypeScript, prefer using TypeScript's native abstract keyword (e.g. abstract class Base {}). TypeScript enforces abstract class rules during compilation, removing the need for runtime validation checks.