Understanding Object-Oriented Programming Features in JavaScript

Hi there! I’m Maneshwar. Currently, I’m building a private AI code review tool that runs on your LLM key (OpenAI, Gemini, etc.) with flat, no-seat pricing — designed for small teams. Check it out, if that’s your kind of thing.

Object-Oriented Programming (OOP) is a paradigm that organizes code into objects—bundles of data (properties) and behavior (methods).

While JavaScript’s OOP model is prototype-based rather than class-based like Java or C#, ES6 introduced the class syntax, making it feel much closer to traditional OOP.

In this post, we’ll explore four important OOP concepts and how they apply in JavaScript: abstract classes, concrete classes, scope visibility, and interfaces.

1. Abstract Classes

An abstract class is a class that acts as a blueprint—it cannot be instantiated directly.

Instead, other classes inherit from it and implement its abstract methods.

JavaScript doesn’t have native abstract classes like Java, but we can mimic them:

class Shape {
  constructor() {
    if (new.target === Shape) {
      throw new Error("Cannot instantiate an abstract class");
    }
  }

  // Abstract method (no implementation)
  draw() {
    throw new Error("Draw method must be implemented");
  }
}

class Circle extends Shape {
  draw() {
    console.log("Drawing a circle");
  }
}

const circle = new Circle();
circle.draw(); // Drawing a circle

const shape = new Shape(); // ❌ Error: Cannot instantiate an abstract class

When to use:

  • To enforce a common structure for related classes.
  • To share partial implementation and force subclasses to fill in the details.

2. Concrete Classes

A concrete class is a fully implemented class from which you can create objects.

It either implements all methods from its parent abstract class or stands alone.

class Rectangle {
  draw() {
    console.log("Drawing a rectangle");
  }
}

const rect = new Rectangle();
rect.draw(); // Drawing a rectangle

When to use:

  • When you have a complete implementation that can be directly used.
  • When you want to define unique behavior for a specific object type.

3. Scope Visibility

Scope visibility determines where and how a class property or method can be accessed.

In JavaScript, ES2022 introduced truly private fields using #, while public is the default.

  • Public – Accessible anywhere.
  • Private (#) – Accessible only inside the class.
  • Protected – Not officially supported in JavaScript, but often mimicked using naming conventions like _protected.

Example:

class Account {
  #balance = 0; // private field

  constructor(owner) {
    this.owner = owner; // public
  }

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

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

const acc = new Account("Alice");
acc.deposit(100);
console.log(acc.getBalance()); // 100
console.log(acc.#balance); // ❌ Error

4. Interfaces

JavaScript doesn’t have native interfaces like Java or TypeScript, but we can simulate them with patterns or enforce them at runtime.

Example using a manual check:

const ShapeInterface = {
  draw: "function",
};

function implementsInterface(obj, interfaceDef) {
  for (let method in interfaceDef) {
    if (typeof obj[method] !== interfaceDef[method]) {
      throw new Error(`Class must implement ${method} as a ${interfaceDef[method]}`);
    }
  }
}

class Triangle {
  draw() {
    console.log("Drawing a triangle");
  }
}

const tri = new Triangle();
implementsInterface(tri, ShapeInterface); // Passes
tri.draw(); // Drawing a triangle

When to use:

  • To ensure different classes share a common contract.
  • To make code more flexible and polymorphic.

Final Thoughts

While JavaScript doesn’t implement OOP features exactly like Java or C#, it’s flexible enough to mimic abstract classes, interfaces, and visibility controls.

ES6+ features have brought JavaScript closer to traditional OOP, while still preserving its prototype-based roots.

If you’re writing maintainable, scalable JS applications, these concepts are invaluable for structuring your code.

LiveReview helps you get great feedback on your PR/MR in a few minutes.

Saves hours on every PR by giving fast, automated first-pass reviews. Helps both junior/senior engineers to go faster.

If you’re tired of waiting for your peer to review your code or are not confident that they’ll provide valid feedback, here’s LiveReview for you.

Similar Posts