DEV Community

Mike Written | AI Trends 24
Mike Written | AI Trends 24

Posted on

I Stopped Writing Classes in JavaScript 3 Years Ago — Here's What Happened

Three years ago, I made a decision that my senior colleagues thought was career suicide.

I stopped writing ES6 classes in JavaScript.

No more class Foo extends Bar. No more constructor(). No more this.something = something scattered across 40-line boilerplate blocks.

Here's what actually happened.


The Problem With Classes in JS

JavaScript classes are not "real" classes. They're syntactic sugar over prototypal inheritance — a fact the language tries hard to hide from you.

When I was writing class-heavy code, I kept running into the same bugs:

  • this behaving unexpectedly inside callbacks
  • Accidentally mutating shared state on the prototype
  • Confusing super() chains that broke silently
  • Unit tests that required elaborate mocking just to instantiate a single object

The deeper I went, the more I realized: I wasn't using classes because they were the right tool. I was using them because they felt familiar from Java and Python.


What I Switched To

1. Plain functions and closures

Instead of:

class Counter {
  constructor() {
    this.count = 0;
  }
  increment() {
    this.count++;
  }
  getCount() {
    return this.count;
  }
}
Enter fullscreen mode Exit fullscreen mode

I now write:

function createCounter() {
  let count = 0;
  return {
    increment: () => count++,
    getCount: () => count,
  };
}
Enter fullscreen mode Exit fullscreen mode

No this. No new. No surprises. The state is genuinely private — not just by convention.

2. Pure functions for business logic

Most "methods" in my old classes were just transformations on data. Once I untangled state from behavior, almost everything became a pure function:

// Before
class OrderProcessor {
  applyDiscount(order, percent) {
    order.total = order.total * (1 - percent / 100);
    return order;
  }
}

// After
const applyDiscount = (order, percent) => ({
  ...order,
  total: order.total * (1 - percent / 100),
});
Enter fullscreen mode Exit fullscreen mode

Testable in one line. No setup. No teardown.

3. Composition over inheritance

Inheritance hierarchies were my biggest time sink. Deep extends chains mean a change anywhere can ripple unpredictably. I replaced them with simple function composition:

const withLogging = (fn) => (...args) => {
  console.log(`Calling with`, args);
  return fn(...args);
};

const withValidation = (fn) => (...args) => {
  if (!args[0]) throw new Error('First argument required');
  return fn(...args);
};

const processOrder = withLogging(withValidation(applyDiscount));
Enter fullscreen mode Exit fullscreen mode

What Actually Changed After 3 Years

My code reviews got faster. Reviewers don't have to trace class hierarchies to understand what a function does.

My tests got simpler. Pure functions don't need mocking frameworks. You pass data in, you get data out.

Onboarding juniors got easier. "It's a function that takes X and returns Y" is always easier to explain than "it's a class that extends this abstract base..."

I stopped fighting this. Seriously. Arrow functions and closures just eliminated a whole category of bugs.

Some things still need classes. React components (historically), custom DOM elements, certain library integrations — classes have a legitimate home. I'm not dogmatic.


The Real Lesson

The goal was never "avoid classes." The goal was to write code that's easy to read, test, and change.

For 90% of my day-to-day JavaScript, functions and plain objects accomplish that better than classes do.

If you're class-heavy right now, I'm not saying throw it all away. But next time you reach for class, ask yourself: would a function and a plain object work just as well here?

More often than not, the answer is yes.


Have you moved away from classes in JavaScript? Or do you think I'm totally wrong? Drop your thoughts in the comments — I read every one.

Top comments (1)

Collapse
 
frank_signorini profile image
Frank

I'm curious how you handled complex state management or