DEV Community

Cover image for Do you need classes in JS/TS?
András Tóth
András Tóth

Posted on • Updated on


Do you need classes in JS/TS?

If you are starting out as a developer, you might run into these conflicting schools of thought: should I write "functional style" with its "pure functions" or go with "object oriented classes"?

The answer would be really long and this is going to be just a quick tip.

Beforehand it is important to know that Javascript (and consequentially TypeScript) is neither functional nor an object oriented language. It has elements of both and it breaks important contracts of either. See the last paragraph: "Only for the curious!".

If you are going to have several similar objects that persist over time (i.e. you keep them around for a long time and you regularly) and have some form of state that you access a class is a really good choice. However if you just need to transform an object to another object a function is your best bet.

The symptoms of not needing a class

The feature a class is truly giving us is accessing this in any of the defined functions. When some or more of your class methods do not access this and only the parameters passed and they also return the result, then you will need a function. Even better if you can make the function pure (in other words none of the parameters passed in are mutated)...

The algorithm to refactor this

  1. Find a class method that do not access this. Extract it into a method and update the depending methods.
  2. Check the class again, if the changed methods no longer access this: move them out as well.
  3. If every method access this you have the real class that is actually managing its own state.

Only for the curious

The classic example of breaking the functional paradigm is that on an array .sort() method mutates the array, while .map() returns you a new array instance. This is inconsistent and creates regular problems.

On the other hand objects created from traditional classes "own" their own functions, while in Javascript you can pass the function of an object and lose its this. You can also bind a function to a totally different object. There is a lot of frustration voiced when this phenomenon dawns on a developer coming from real object oriented background.

Questions, mistakes or do you wish examples? Blogging and learning is a collaborative effort, I need your help to help you. 🤝 Let me know in the comments! Cheers!

Top comments (11)

lukeshiru profile image
Luke Shiru

My answer would be that you don't need classes. If you need encapsulation you can use the module system, and if you need to hold internal state, you can use closures, or even generators, so you don't need classes for that either. My general advice is: Try to code something and before defaulting to a class, think how can you write that if it was only a function. Generally that solution is cleaner, easier to maintain and test.


fjones profile image

It depends very much on the programming paradigm you apply. Traditionally OOP applications benefit from classes in JS, but is that the kind of JS we want to write? Do we prefer functional programming, or do we want to go back to using the actual design of the language and relying on prototypes?

Functional programming is certainly seeing a new renaissance in JS, but rarely in the terms that are actually related to traditional functional programming (pure functions, higher-order-functions, declarative programming). Prototype-based programming is all but gone, save for polyfills. It's certainly an interesting development.

lukeshiru profile image
Luke Shiru

A very common misconception is that OOP and classes are the same thing, or that you need classes in order to do OOP. They are related, but only because classes are "one way of doing encapsulation", in languages like JS/TS there are better ways. Just because you don't use classes, that doesn't mean you aren't doing OOP. There's a great article by Eric Elliot about this, but long story short is that you can do OOP without classes (and I'm not talking about using prototype, because that's just a more verbose way of using class nowadays).

Thread Thread
fjones profile image

I agree with most of this (particularly the relative verbosity of class vs prototype), though I would argue that classes in JS are still the better way to do OOP. OOP isn't just about encapsulation, it's about polymorphism and data transmission just as well. All of those are certainly helped by a clear class structure over module-based encapsulation.

Thread Thread
peerreynders profile image
peerreynders • Edited

Prototype-based programming is all but gone, save for polyfills.

class keyword or not - the objects instantiated still rely on prototypal inheritance. And in performance conscious code bases constructor functions are still "assembled" - that way method implementations can be shared by otherwise unrelated constructor functions (see Preact).

class vs prototype

Class free OOP doesn't relate to implementing inheritance with prototypes. "OOP with functions" typically refers to a plain literal object holding references to functions that share data through the closure of the factory function that created them.

function createDog(name) {
  let hungry = false;
  return {
    get type() {
      return 'dog';
    get name() {
      return name;
    set name(n) {
      name = n;
    get isHungry() {
      return hungry;
    play() {
      hungry = true;
    feed() {
      hungry = false;
    makeSound() {
      alert(hungry ? 'groan....' : 'Woof woof.');
Enter fullscreen mode Exit fullscreen mode

OOP with functions in JavaScript
How to decide between classes v. closures in JavaScript.

classes in JS are still the better way to do OOP.

Keeping in mind that in JavaScript Classes are a template for creating objects - for the most part they are just a creational convenience (until more is needed) but they are not the only way to create objects in JavaScript; unlike in mainstream class-based object-oriented languages.

James Coplien
"How many of you do object-oriented programming? What language? Java is the only language in which you cannot do object-oriented programming. Huh? Other languages. Smalltalk - no. C# - no. Python - no. No. Any JavaScript programmers here? Here are my object-oriented programmers - they're writing objects - the rest of you are writing classes. "

it's about polymorphism

JavaScript has always achieved polymorphism through "duck typing" - no classes required. TypeScript's structural typing is an expression of that. Either a value satisfies an interface or type alias or it does not - no need to implement, inheritor extend anything.

clear class structure

More often than not I hear people complaining about brittle, deep, complex class hierarchies.

"Favor object composition over class inheritance"
Gamma, Erich et al. "Design Patterns Elements of Reusable Object-Oriented Software". Putting Resuse Mechanisms to Work, p.20, 1994

So a "clear class structure" doesn't seem to be a pit of success for OOD/P in practice.

Functional programming is certainly seeing a new renaissance in JS.

I think that is a red herring. I myself have described JavaScript as function-oriented but using an FP-flavoured expression-based (as opposed to statement-based) style leads more to value-oriented programming.

Thread Thread
lukeshiru profile image
Luke Shiru

Tell me you're planning on writing an article. Every time I read a comment of yours is excellent 🤩

latobibor profile image
András Tóth • Edited

Prototype-based programming is truly gone, I only realized it when I failed an interview question about prototypal inheritance. "Well" I said "I haven't written anything prototype related in the last 4 years."

Onto the other approaches: since the language was not designed for either, doing them as they were written requires ugly hacks and clunky solutions. For the love of god I despise for example when I see a trainwreck like myThing(354)('adf')((_, stuff) => stuff.process()). If you stick to the basic rule of being as clear as possible with the least amount of boilerplate you won't use anonymous function compositions nor you won't fire up a whole dependency injection system just you can mock two dependencies for a test.

pengeszikra profile image
Peter Vivo

Imho I prefer the functional programming over OOP.

  • Each class function have dependency of whole class.
  • Harder to handle class before crated vs. variable before created.
  • Much simple to write a function than class.
  • don't need to worried about this
devfranpr profile image
lukeshiru profile image
Luke Shiru

You know me so well

devfranpr profile image

I know you're going to react to this and I want to learn more.

Visualizing Promises and Async/Await 🤯

async await

Learn the ins and outs of Promises and Async/Await!