Please stop using classes in JavaScript

For years, OOP (object-oriented programming) was the de-facto standard in software engineering. The concepts of classes, polymorphism, inheritance, and incapsulation dominated and revolutionized the development process. But everything has an expiration date, programming paradigms included. In this article I will talk about why were classes introduced in the first place, why it is a bad idea to use classes in JavaScript, and what are some of the alternatives.

I am not going to talk about why OOP is fading away in general, but you can check out this great article for more info.

Pre-ES6 classes

Even though the class keyword was added to JavaScript since ES6 (ECMAScript 2015), people were using classes earlier. The way to achieve this was constructor functions and prototype delegation. To show you exactly what I mean, I am going to implement the same class in ES5 and ES6 environments. Consider a class Car and SportsCar that inherits Car. Both of them have make and model properties and start method, but SportsCar also has the turbocharged property and overrides the start method:

As you probably guessed, the Car (line 2) and SportsCar (line 18) functions are constructor functions. The properties are defined using this keyword and the objects themselves are created with new. If you are not familiar with prototype, this is a special property that every JS object has to delegate common behavior. For example, the prototype for array objects has the functions you probably know well: map, forEach, find, etc. The prototype for strings has functions replace, substr, etc.

After the Car object is created on line 33, you can access its properties and methods. The call to start on line 34 results in the following actions:

  1. The JS engine asks the car object for a value with the key start.
  2. The object responds that it has no such value
  3. The JS engine asks the car.prototype object for a value with the key start.
  4. the car.prototype returns the start function, that the JS engine executes immediately.

Accessing the make and model properties are performed similarly, except they are defined on the car object directly, instead of the prototype.

Inheritance is a bit trickier. It is handled on lines 24-25. The most important function here is the Object.create function. It accepts an object and returns a brand new one, with its prototype set to whatever was passed as an argument. Now, if the JS engine does not find a value on the sportsCar object or sportsCar.prototype, it will consult sportsCar.prototype.prototype which is the prototype of the Car object.

ES6 Class keyword

With the release of ES6 in 2015, the long-awaited class keyword arrived in JavaScript. It was done as per numerous requests by the community because people were feeling uncomfortable coming from object-oriented languages. But they missed one important point.

JavaScript has no idea what classes are

JavaScript is not an object-oriented language, it was not designed to be one, the notion of classes is absolutely not applicable to it. While everything in JS is indeed an object, these objects are different from the ones in Java or C#. In JS, an object is simply a Map data structure with a somewhat sophisticated lookup procedure. That is it, really. And when I say everything is an object, I mean it: even functions are objects. You can check it with this snippet:

Ok, this is all good, but how does the class keyword work then? Glad you asked. Do you remember the Car and SportsCar example earlier? Well, the class keyword is simply syntactic sugar on top of that. In other words, class produces conceptually the same code and serves only aesthetic and readability purposes. As I promised earlier, here is an example of these same classes in ES6:

These examples are identical and produce the same result. What is interesting, they produce (almost) the same code under the hood. I will not write it out here, but if you are curious, head out to the online Babel transpiler and have a look at the output.

Why not?

Now you should have an understanding of what classes in JS are and how they work. Now, with all this knowledge, I can explain why using classes in JS is a bad idea.

  1. Binding issues. As class constructor functions deal closely with this keyword, it can introduce potential binding issues, especially if you try to pass your class method as a callback to an external routine (hello, React devs ๐Ÿ‘‹)
  2. Performance issues. Because of classes’ implementation, they are notoriously difficult to optimize at runtime. While we enjoy performant machines at the moment, the fact that Moore’s law is fading away can change all that.
  3. Private variables. One of the great advantages and the main reasons for classes in the first place, private variables, is just non-existent in JS.
  4. Strict hierarchies. Classes introduce a straight top-to-bottom order and make changes harder to implement, which is unacceptable in most JS applications.
  5. Because the React team tells you not to. While they did not explicitly deprecate the class-based components yet, they are likely to in the near future.

All of these issues can be mitigated with JS objects and prototype delegation. JS offers so much more that classes can ever do, yet most developers are blind to it. If you want to truly master JS, you need to embrace its philosophy and move away from dogmatic class-based thinking.

Get new content delivered to your mailbox:

23 comments

  1. my god | may 14, 2020

    you have to be 16 to still fall for this “such and such technique/methodology/language is dying” specially with our long, long , looong history of how freaking difficult it is to kill anything in computing… hell we had to make a fucking decades old campaing to kill IE, and there’s still people who have to deal with it today (and no they don’t have a choice).

    Just stop prefacing every good article you write with some futurology bs, you don’t have to/ can’t predict how the whole world will behave based only on whats on your own backpack

    • michael krasnov | may 15, 2020

      Chill, dude. I am merely expressing my personal opinion on how quality JS code should look like, and certainly not trying to bury OOP completely.

  2. nic | may 18, 2020

    Very nice article. Unfortunately JavaScript suffers from being mainstream language, and they are adding a lot of syntax sugar (or garbage) in order to conform to existing paradigms. That’s all about people are not willing to learn the language in depth, companies are not willing to pay for educating their employees, etc. It’s pity because many don’t use the real power of JS because of this, that can enable writing simple and efficient code.

  3. eric cavazos | july 1, 2020

    I agree with you and itโ€™s sad that because of the influence of other languages, classes have been targeted as the way to do things, but not needed. I think this stems from Javascript becoming so popular and developers from languages such as Java coming in with a heavy-handed influence. unfortunately.

    I worked on a large codebase that had classes for an API and we constantly had memory issues with Nodejs using classes. We took on an undertaking of removing and not using classes, but taking a more functional approach and the memory saving was more than 82%

  4. grey himmel | august 22, 2020

    Hi! I’d like to point out that something in this article is very misleading. You mention that React might be removing class support in the near future, in point number 5.
    While yes, React does mention that classes can be confusing and that there are several advantages to using hooks over classes, they also explicitly state that they don’t plan to remove class-based component support “for the foreseeable future.” This is stated multiple times in the page linked there. It might be good to read a source thoroughly before citing it in the future!

    • michael krasnov | august 22, 2020

      I read this documentation, thank you very much. Of course, react team cannot do this in the foreseeable future, but this does not cancel the fact that they (1) want to and (2) they can’t yet because of us

leave a comment