DEV Community 👩‍💻👨‍💻

Johnny Araujo for Giant Machines

Posted on

Stop Using JavaScript Classes!

angry pixar character from Inside Out

Are you mired in a JavaScript codebase full of classes? Are you new to JavaScript and tempted to reuse patterns from object oriented languages? Do you ever wonder if there's a better way of doing things in JS?

Fear not! By learning to write idiomatic JavaScript utilizing modules instead of classes, you can write code that is less cumbersome, more readable, easier to maintain, and provides a more pleasant engineering experience overall. In this article, I'll show you why classes should be avoided in idiomatic JavaScript, and why modules should be your go-to choice.

*Note: You should be somewhat familiar with object oriented programing (OOP) and JavaScript (JS) before proceeding.

The Problem:

Below is an example of the kind of JavaScript I often see in the wild:

class ContrivedClass {
  constructor(db) {
    this.db = db
  }

  getPerson() {
    return this.db.getPerson();
  }
}
Enter fullscreen mode Exit fullscreen mode
// somewhere else in the code, this class is only called once

const contrivedClass = new ContrivedClass(db);
const person = contrivedClass.getPerson();
// do something with person
Enter fullscreen mode Exit fullscreen mode

Above you see a JavaScript class with only one method and one constructor argument for injecting a dependency, and the class is only ever instantiated once. And my reaction is always the same…

blank stare at computer

Why is this my reaction? Because in JavaScript, there exists a plethora of better ways to write code, and yet in some codebases, classes seem to dominate more than Michael Jordan in Space Jam! (Sorry, Lebron.)

You seem upset. What are classes and why do you have opinions about them?

To understand why classes should not be the preferred way of organizing JavaScript code, we must first understand what classes are and where they excel. According to Oracle’s Java documentation, in object-oriented-programming, an object “stores its state in fields (variables in some programming languages) and exposes its behavior through methods (functions in some programming languages). Methods operate on an object's internal state and serve as the primary mechanism for object-to-object communication”. A class, then, is “the blueprint from which individual objects are created”.

The structure of the class typically includes instance fields, a constructor, and methods:

  • Instance fields hold values as local state for the instantiated class.
  • A constructor is a method that receives the arguments the class needs in order to be instantiated and utilizes those arguments to return the instance of the class (the "object").
  • Methods are functions that often manipulate the instantiated class's data. Methods typically come in 2 forms, public and private:
    • Public methods are functions that can be called outside of the instantiated class by other code that utilizes the object.
    • Private methods, as noted by their name, cannot be called outside of the instantiated class.
    • Private methods are utilized by public methods or even other private methods to accomplish tasks where the implementation details are not relevant to the code using the instantiated class.

Below is a simple example of how to utilize a class that highlights many aspects of classes that programmers find attractive. The class provides a clear distinction between what the code consuming the class needs to be aware of and what it doesn’t. The class has built-in mechanics for how you write code, store data, manipulate data, and expose data. It’s easily reproducible—just use the new keyword to create another instance of the class to your heart's content. It even has capabilities for more advanced techniques such as inheritance, which can limit the work required to do similar but distinct tasks, but also has its drawbacks.

class Book {
 // declare the values you want to store as part of this class
 author;
 title;
 readCount;

 // declare how the instance fields will get initialized
 constructor(author, title) {
   this.author = author;
   this.title = title;
   this.readCount = 0;
 }

 // create a private method that abstracts an implementation detail for use by a public method
 incrementReadCount() {
   this.readCount += 1;
 }

 // create a public method that can be executed outside of the class 
read() {
   console.log('This is a good book!');
   this.incrementReadCount();
 }

 getReadCount() {
   return this.readCount;
 }
}
Enter fullscreen mode Exit fullscreen mode
// somewhere in a different code block

const myFirstBook = new Book('Jack Beaton', 'Getting To Mars');
myFirstBook.getReadCount(); // 0
myFirstBook.read(); // 'This is a good book!'
myFirstBook.incrementReadCount(); // calling private methods outside the class won't work in strict OOP languages
myFirstBook.read(); // 'This is a good book!'
myFirstBook.readCount; // directly accessing a class's private fields won't work in strict OOP languages
myFirstBook.getReadCount(); // 2
Enter fullscreen mode Exit fullscreen mode

Classes seem pretty cool! So what’s so bad about using them in JS?

There’s nothing inherently bad about using this pattern in JS. However, the problem I’ve frequently encountered is that this is sometimes the only pattern, or a frequently misused pattern, in a JS codebase. When deciding between what patterns to use, the team should pick the pattern that best addresses the problem being solved in the language being used. But if the OOP pattern of classes is the only way you know how to or like to code, then of course there will be times when using it will make the code harder for others to understand because the pattern is not a natural fit for the problem and/or programming language.

a cat trying to fit in a container

So what is an alternative to classes in JS?

JS modules, of course.

What’s a JS module?

In JavaScript, a module is a file that exports features, such as variables, objects, and functions, that can be used elsewhere. They are defined using the export syntax, and code within the module will have scope access to all variables declared in the file in which it was defined. The exported features can then be imported into any other file or module. But code outside of the module will not have access to code in the module that hasn't been exported.

The variables you export can take any shape, including a class, as long as it’s a valid JS variable, function, or object. In practice, this means that in a given file, we might declare variables outside of a data structure but still use them within the structure. This is called a closure. In other languages this is not allowed, but JS has robust support for closures.

// some js file

const a = 1;
const b = 2;

export function add() {
 return a + b;
}
Enter fullscreen mode Exit fullscreen mode
// some other js file that imports the add() function

add(); // 3
Enter fullscreen mode Exit fullscreen mode

So how might we code the Book data structure using a JS module instead of a class?

Like this:

// some js file

// the exported function is what other modules will have access to
export function createBook(authorName, bookTitle) {
 // the following variables and functions are declared within the scope of the createBook function so other book instances or code cannot access these variables
 const author = authorName;
 const title = bookTitle;
 let readCount = 0;

 function incrementReadCount() {
   readCount += 1;
 }

 function read() {
   console.log('This is a good book!');
   incrementReadCount();
 }

 function getReadCount() {
   return readCount;
 }

 // only the methods listed as key-value pairs can be accessed by the returned Object
 return {
   read,
   getReadCount,
 };
}
Enter fullscreen mode Exit fullscreen mode
// in some other file

const mySecondBook = createBook('Gabriel Rumbaut', 'Cats Are Better Than Dogs');
mySecondBook.getReadCount(); // 0
mySecondBook.read(); // 'This is a good book!'
mySecondBook.incrementReadCount(); // will throw an error
mySecondBook.read(); // 'This is a good book!'
mySecondBook.readCount; // will also throw an error
mySecondBook.getReadCount(); // 2
Enter fullscreen mode Exit fullscreen mode

As you can see, all the things we love about classes are in our module, without having to use the class syntax. There’s less boilerplate as instance fields and methods are replaced with simple variables, and their status as public or private is denoted by their inclusion or exclusion in the return of the exported createBook function module. By exporting a function that explicitly returns an object, we are able to forego the new syntax completely.

But what about dependency injection?

It is true that many like using classes in JS because the constructor function allows for easy dependency injection, where we pass in dependencies to the new object rather than hard-coding and coupling them to the class. For example, if my class requires making calls to a database, I can configure the constructor to receive a DB instance. This is fine as well, but remember, JS natively allows for the importing of modules created elsewhere! So if you want access to that DB instance, export it as a module and import it in the module where you actually need it. You get all the benefits of dependency injection without classes!

// old: db created or imported here and passed into Class
const library = new Library(db);

// new: db created or imported here and passed into Module
const library = createLibrary(db);
Enter fullscreen mode Exit fullscreen mode

Moreover, you might not need dependency injection. Unless you are going to construct different Library instances with different DB instances, importing the DB directly into the module hosting the Library class/function will save you from having to write redundant code across multiple files. If you don't foreseeably need dependency injection, there's no need to go out of your way to support it.

// alternate #1: db imported within the Class
const library = new Library();

// alternate #2: db imported into Module
const library = createLibrary();
Enter fullscreen mode Exit fullscreen mode

If I can do everything using modules, why do I need classes?

In JavaScript, you don’t! You can write any program you want without utilizing classes or the this keyword ever! Indeed, the class syntax is somewhat new to JavaScript, and object oriented code was written with functions beforehand. The class syntax is just syntactic sugar over that function-based approach to OOP.

So why do I see classes so often?

Because prior to ES5, most people didn’t take JS seriously as a language. The inclusion of class syntax in JS was an intentional decision to attract these more experienced programmers and lower the barrier of entry to make JS more popular. It worked extremely well, but at a cost. Since most people learned JS after learning an OOP language like Java, C++, or even Python or Ruby, it was easier to just rewrite what they already knew using JS syntax. And when newbies wanted to learn JS from scratch, they had all this OOP JS code as real life examples for how to implement common structures, so they too are now OOP programmers.

I get the sense you don’t actually think anyone should use classes in JS.

What gave that away 😃? For reasons that Kyle Simpson lays out in much more detail than I ever could, classes are not first class citizens in JS in the same way that they are in other languages. Most don't know this, but under the hood, all classes are functions, and all functions are objects. (Arrays are objects, too, but that’s besides the point.) As a result, you are better off in most cases just writing objects and functions directly as it is more behaviorally consistent, more pleasant to maintain, less cumbersome to write, and easier to read. That way when your peers look at your code, they aren't feeling confused like Johnny from Schitts Creek.

person confused by papers they are handed

So classes in JS are a choice, not a way of life. I get it. In your opinion then, when should I use them and when should I avoid them?

Consider using classes when:

  • Most of the team is unfamiliar with modules
  • The code you are writing is not expected to be an exemplar of idiomatic JS code
  • You want to leverage broadly known patterns that are strongly enforced in a class paradigm (e.g., local state, public/private, etc.)
  • You plan on instantiating a given class multiple times
  • You don’t always instantiate classes with the same arguments
  • You plan on leveraging all or most of a class’s capabilities (i.e., inheritance, dependency injection, etc.)

Consider avoiding classes when:

  • You only instantiate your class once in a given runtime
  • Your data structure does not require any local state
  • You have minimal public methods
  • You aren’t extending your data structure to create new ones
  • Your constructors are only used for dependency injection
  • Your constructors are always called with the same arguments
  • You want to avoid using this

But I like using classes in JS. Do you really think I should abandon them?

Yes! But more importantly, I just need you to know that you have other options. Not just in coding, but in life. If you challenge basic assumptions about the way you do things, you will discover and learn much more than if you continue to do things as you always have.

If you still feel strongly about using classes or are under constraints that prevent you from properly implementing modules, that’s fine. If anything, you are in luck because TC39 is adding public/private/static syntax into the next version of JS, ES2022. But please be sure to understand the implications of your decision, especially if the classes you write don’t utilize all the benefits that classes have to offer!

For more information on all the different types of patterns you can use for coding in JavaScript, please see Learning JavaScript Design Patterns by Addy Osmani.

Top comments (28)

Collapse
 
raslanove profile image
raslanove • Edited on

Ummm. I don't see why you are trying to avoid classes, they are useful and as you mentioned, soon they will be getting more powerful. And you haven't replaced classes with modules, you replaced them with closures. And after removing the comments and blank lines, both implementations of your book class/closure took the same number of lines.

Seriously, your point flew over my head. You are replacing classes with something less flexible, with no gains at all. Modules are nice, and they can be used to wrap classes just like they wrap closures. So, the module point is out of the window.

And about being "more behaviorally consistent", "more pleasant to maintain", "less cumbersome to write", and "easier to read". Really? In what way? Shouldn't you have explained these before concluding them?

Instead of telling people not to use classes, this would have been a nice article about closures and how they can be used for those who have class-phobia.

Collapse
 
jaraujo6 profile image
Johnny Araujo

Thanks for reading! To be honest I care less about how people code and more that they understand the language that they are coding in. I tried to bring that point home in the end so sorry if that didn't come across. I'll do better next time ;)

Collapse
 
lukeshiru profile image
Luke Shiru

I wrote about this same topic a few years ago. The main argument folks have in "favor" of classes is "code organization", which from my point of view is not sound when you consider that you can use the file system and modules for organization. But yeah, brace yourself, people that like classes really dislike to be told that they don't need them, so you might received some heated comments.

The main issue is that CS degrees still teach classes as the holy grail of coding, when in languages like JS they aren't necessary at all. They were mainly added to appeal to developers of other languages such as Java, and keep expanding the "multi-paradigm" approach of JavaScript itself.

Good luck with those comments!
Cheers!

Collapse
 
lukeshiru profile image
Luke Shiru • Edited on

BTW, from my point of view, a better alternative for the Book example would look something like this:

const createBook = ({ author, title }) => ({ author, title, readCount: 0 });

const incrementReadCount =
    increment =>
    ({ readCount, ...book }) => ({ ...book, readCount: readCount + increment });

const read =
    messsage =>
    book => (console.log(message), incrementReadCount(1)(book));

const getReadCount = ({ readCount }) => readCount;

// And then you use it like this:

const mySecondBook = createBook({
    author: "Gabriel Rumbaut",
    title: "Cats Are Better Than Dogs",
});
getReadCount(mySecondBook); // 0
read("This is a good book!")(mySecondBook); // Logs "This is a good book!", returns book with extra read count
incrementReadCount(1)(mySecondBook); // Returns book with extra read count
Enter fullscreen mode Exit fullscreen mode

I used currying and immutability just to make it sweeter <3

Collapse
 
jaraujo6 profile image
Johnny Araujo

This is pretty cool! I never curry as much as I would like to in practice! Thanks for reading!

Re: heated comments....it's not to bad here on dev.to but on the medium cross post....LOL

Collapse
 
raslanove profile image
raslanove

Well, object oriented is a pretty strong and established programming paradigm. And it was introduced mainly for code organization! And object oriented is not about classes. It's about encapsulation, polymorphism and inheritance. The alternative that the author is suggesting is STILL OBJECT ORIENTED! Just a different syntax. If he was suggesting a different paradigm, like function or data oriented, maybe the article would have been more useful.

The reason why the article is getting heated comments is because the author is asking for them. You can clearly see that from the graphics used in his article. Besides, the use of strong language, like "Don't use classes" gives you the feeling that you are going to behold a great change. In a field where there's no absolute right and wrong, you expect someone telling you not to do something to have a pretty strong argument. Honestly, I feel like I was click-baited.

Collapse
 
lukeshiru profile image
Luke Shiru

One thing is object oriented programming and another thing is classes. Classes is just one way of achieving encapsulation (and a pretty limited one, based on inheritance, which sucks). From my point of view is still ok to say that we don't need classes for OOP and make examples showing how we can do the same things we could do with classes, but without them, not to mention internally they still are pretty much just functions syntax sugar on top (similar to how some folks learn async/await without properly understanding promises).
I mean, I agree that "the point of not using classes is avoiding their limitations", but I think the idea of the author was to show that even for stuff that seem to be "class only" we can still avoid classes and just use functions.

Thread Thread
 
raslanove profile image
raslanove

Encapsulation is associating the code with the data it acts upon. It has nothing to do with inheritance. Closures do the same, they associate the code with the data.

It's ok to say we don't need classes. It's not ok to say "Hey! Don't use classes. They are inferior!". The author has shown a nice technique to avoid using classes, but he didn't state valid reasons to avoid them in the first place. Yet, he was very assertive about his stance, which some of us find less appealing. This could mislead some beginners into believing his -so far- baseless assertions. He could present his findings as another way to do things, not as the "correct" way to do things. That's the whole point I'm trying to make.

Thread Thread
 
lukeshiru profile image
Luke Shiru

You're right about the encapsulation thing, I didn't expressed myself correctly (sorry, english is not my native language 😅). My point was that there are better ways of achieving encapsulation (using modules and closures), and also classes take you into the inheritance path ("is" relationships), which sucks compared to composition ("has" relationships, that can also be considered "is").

About the way the article is expressed, I get what you mean. Maybe I kinda agree with the point of not being a "correct way" of doing stuff, but at least for beginners, from my point of view, just teaching functions is way simpler than having to also introduce classes and all that jazz. I mean is ok to mention them (as you would mention stuff like eval, which is also part of the language, but is far from ideal).

Collapse
 
metcoder profile image
Charlie Fuentes

Hey! Nice work with the Article, but I think the code focus way to much on high level implications rather than low-level ones. Meaning the implications of using Classes and how they really relate with JS prior ES6.
Overall, Classes came to allow more people easily start using the concept of Object without fully needing to understand/learn Prototype Oriented Programming which is what JS implements under the hood. Along with that, Classes does pretty more couple of things that easies the need for dealing with this and for instances Classes and Instances as well.

The Article quite implies that modules are better than Classes which is not the case, and they shouldn’t be compared as are totally different things. A more real comparison is to construct Objects out of Functions and export them, or use Prototype for attaching methods and more.

Again, will be better to compare it to other things instead of directly against modules :)

Collapse
 
jaraujo6 profile image
Johnny Araujo

Hi Charlie, thanks for reading! That focus was intentional because users such as yourself have a better low level grasp and aren't as quick to use these patterns. In my honest opinion if you know what you're doing, you can do whatever want, but many people have limited exposure and tend to run with whatever they've seen.

Regarding classes vs functions with methods, that's exactly how JS classes work under the hood so it wasn't an alternative I was interested in exploring. Good point though!

Collapse
 
metcoder profile image
Charlie Fuentes

Hi Johnny :)

Sure you’re right on your first point, for new adopters it can be easy pick this approach mostly if your coming from a OOP language background like Java or C# (which are the most common), and I also do agree that as long as you’re confortable with what you’re doing it, should not be a problem at all :)

Sure! I felt it like more natural to compare as even that the JS Modules kinda can work like this, sometimes new adopters can confused them with what the Classes are really trying to achieve in JS. Thanks a lot for the feedback! Keep it going 🙌

Collapse
 
smpnjn profile image
Johnny Simpson • Edited on

I actually think it's more confusing having two paradigms. I sometimes open Javascript files that are written as classes and it takes me a little it of time to understand exactly what they were trying to accomplish since I'm used to working differently in JS. I'm sure it's the same if a OOP programmer opens a prototype/object based Javascript file.

Anyway, I'm not even sure classes in Javascript really give OOP programmers all the flexibility that classes in other languages do. Fortunately that's changing with the inclusion of things like decorators. Since classes in Javascript are purely syntactic sugar, I also wonder what extra you are getting? It's not like there's extra functionality that comes with classes.

Collapse
 
jaraujo6 profile image
Johnny Araujo

Hi Johnny! Thanks for reading! It's definitely best if teams discuss beforehand which patterns to use and which to avoid. Consistency I find is usually more important than the patterns you end up sticking with.

Collapse
 
assertnotnull profile image
Patrice Gauthier

Classes in Javascript are very basic. The real benefit is DI when using decorators with Typescript. In one of my previous work I saw that if there's no clear structure in place it becomes a mess and over time I feel now that JS development suffers from a common structure, conventions. At scale the benefit of DI becomes useful but then when you reach that stage then you already have a mess that is too big to tackle and not worth it business wise. Developers create low quality code as result and best practices are an ideal in theory. Functions with 600 lines were looked over like it's fine and the company was just 5 years old. We really need to use something like Nest.js.

Collapse
 
jaraujo6 profile image
Johnny Araujo

Nest.js is one of the few exceptions I make when it comes to using classes in Node. Thanks for reading!

Collapse
 
kulaggin profile image
KulaGGin

DI becomes useful immediately with 0 lines of code. The mess will slow you down in minutes, not years. There is no excuse not to use best practices such as TDD and applying design patterns even for personal projects.

Collapse
 
x1unix profile image
Denis Sedchenko

You definitely can replace classes with modules in the same way as you can just use static classes/methods in Java/C#/etc instead of object instances, but...

DI allows you to achieve loose coupling in your codebase and convenient mocking of different subsystems in your project's unit tests.
This very helps if you're working on a relatively large monolith project.

Collapse
 
jaraujo6 profile image
Johnny Araujo

If it's the right tool for the job, by all means. Thanks for reading!

Collapse
 
urielsouza29 profile image
Uriel dos Santos Souza

Very good

Collapse
 
jaraujo6 profile image
Johnny Araujo

Thanks for reading!!

Collapse
 
dannyengelman profile image
Danny Engelman

I just need you to know that you have other options.
Not just in coding, but in life.

On our First Date you will probably tell me to hold the fork in my left hand.

Collapse
 
jaraujo6 profile image
Johnny Araujo

That's hilarious! Thanks for reading!

Collapse
 
brandonpsmith profile image
Brandon Smith • Edited on

While everyone is hanging on to classes, massive frameworks like React (hooks) and Vue (composition api) are moving away from them? We will come back full circle once we realize that classes are not really needed, this is one of the most confusing things you can teach to a beginner, and composition > inheritance.

Collapse
 
kulaggin profile image
KulaGGin

composition > inheritance

Wrong. They're not competing. They're just different tools for different situations. It's like saying "saw > hammer". In some situation the hammer is better, and in other the saw is better.

We will come back full circle once we realize that classes are not really needed

They're absolutely not needed. You can just create one method main and put all your global variables about it and code it like that, sure.

Collapse
 
kulaggin profile image
KulaGGin • Edited on

Nice rant.

Why is this my reaction? Because in JavaScript, there exists a plethora of better ways to write code, and yet in some codebases, classes seem to dominate more than Michael Jordan in Space Jam! (Sorry, Lebron.)

There's nothing wrong with organizing your code in classes. It's actually a very good way when language supports it. I'd say it is the best way generally. Everyone understands classes. If they don't understand classes, are they even really a programmer?

Above you see a JavaScript class with only one method and one constructor argument for injecting a dependency, and the class is only ever instantiated once. And my reaction is always the same…
Image description

So? There's nothing wrong with having a class even when you create only one instance, same as there is nothing wrong with having a closure when you only have only one instance. I often enough create classes in other languages of which I only have one instance at runtime but it makes it easier to test the module(dependency injection and substitution with mocks or objects with specific state in tests).

Anyway, in your rant about classes vs closures this paragraph of yours doesn't add any value and isn't an argument against classes in the classes vs closures debate. Having one instance at runtime is just fine in either case. Moving on.

According to Oracle’s Java documentation, in object-oriented-programming, an object “stores its state in fields (variables in some programming languages) and exposes its behavior through methods (functions in some programming languages).

Having fields is not an attribute of an object in OOP. And it's easy to demonstrate. Take any interface, then create an object that implements that interface and make that object save its state in the database by calling some static functions in a namespace. Now you have an object that fulfils your requirements, implements an interface, stores its state in a database. You can program against an interface, use that object successfully, yet, that object has no fields.

Methods operate on an object's internal state and serve as the primary mechanism for object-to-object communication”.

Wrong again. Not long ago I've created a IKeyboardGateway interface with method GetKeyboardState and created an implementation of that interface: KeyboardGateway that returns an array of size 255 with the state for each key of the keyboard. The KeyboardGateway object didn't operate on an object's internal state. The KeyboardGateway object called system's GetKeyState function(Windows in this case for me).

Other modules that used IKeyboardGateway object didn't know it was implemented using the KeyboardGateway class. All the other modules knew is IKeyboardGateway and about one method: GetKeyboardState. That's where OOP is happening: in programming against interfaces. Not in creating classes with a bunch of fields and methods. You can have solutions with classes all over the place in each and every file, and have nothing other than classes, and do no object-oriented programming: all of your dependencies will be hardcoded to specific implementations.

Uncle Bob nicely explains what OOP is and what an object is here:
youtu.be/oar-T2KovwE?t=3246

There’s nothing inherently bad about using this pattern in JS. However, the problem I’ve frequently encountered is that this is sometimes the only pattern, or a frequently misused pattern, in a JS codebase.

Yeah, there's nothing wrong with using classes in JS. And yeah you can write very bad code with classes. Same as with closures.

But if the OOP pattern of classes is the only way you know how to or like to code, then of course there will be times when using it will make the code harder for others to understand because the pattern is not a natural fit for the problem and/or programming language.

That's too vague and needs some concrete example which would demonstrate that. And I doubt it will happen. If we implement the same thing with closure, it'll be just as hard to understand.

So what is an alternative to classes in JS?
JS modules, of course.

JS modules aren't alternative to classes in JS. Alternative to classes is closures. In your example later you provided alternative solution with closure, not module. Module can export either a class or a closure.

There’s less boilerplate as instance fields and methods are replaced with simple variables

False again. You don't need to declare fields in a class(outside of functions). You can just set them in a constructor, same way you did in a closure. You'll just have to add this..

and their status as public or private is denoted by their inclusion or exclusion in the return of the exported createBook function module

This is additional boilerplate code: you need to return a whole struct with variables in it.

In classes you declare private fields with this.#myVariableName and in closures you return the struct with public fields available for use. That's around the same amount of boilerplate code.

Moreover, you might not need dependency injection. Unless you are going to construct different Library instances with different DB instances, importing the DB directly into the module hosting the Library class/function will save you from having to write redundant code across multiple files.

No. It's not about redundant code. It's about managing the dependencies.

Collapse
 
craigstowers profile image
Craig Stowers • Edited on

I didn't want to use classes in my latest project for some of the reasons stated here, but they're actually much faster in some use cases (at least from my tests creating thousands of instances).

If you want the following features: inheritance/extending, overriding getters/setters on sub classes (key word "overriding"), then you can't beat classes in javascript.

I've toyed around for ages with factory function+mixins, and prototypes. I don't know what's going on under the hood but there are huge penalty's with non-class based patterns that allow for getter/setter overrides. Unless someone can show me a pattern that works (it's a hard topic to find information on actually), then I'm running on the assumption that browsers have optimized classes in some special way when it comes to my use case.

I'm guessing the browser translates class code to objects/prototypes for each sub class. Meaning that it builds one generator it re-references for each sub class and thus avoids going through the slow mixin process that assigns/joins objects on every instance in a factory/prototype pattern. (You need mixins to override getters/setters as far as I know, but I'd love some guidance if another way).

Collapse
 
kahunacohen profile image
Aaron Cohen

I don't find this a particularly strong argument. And this is coming from someone who generally avoids classes in JavaScript. That said, I don't think referencing a module-level variable is a "closure." A closure is defined as:

"A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function."

I think what is commonly meant as a closure is the private scope of a function's outer scope. A closure is another function that "closes over" that private scope. The local variables are not observable or mutatable outside the function's scope.

A module-level variable, on the other hand, is observable by either other functions in the module, and even functions outside the module (if exported).

One of the reasons your argument isn't persuasive is that I'm not sure you've done your homework.

A more reasonable way to accomplish what you are trying to do is by actually using closures and returning functions that close over private state. This is, in fact, probably what the class based syntax transpiles down to when using Babel.

18 Useful Github Repositories Every Developer Should Bookmark

>> Check out this classic DEV post <<