Download as pdf or txt
Download as pdf or txt
You are on page 1of 1

Sign in Get started

WRITE FOR US ARCHIVE PLAINENGLISH.IO


JavaScript in Plain English
New JavaScript and Web
Development content every
day. Follow to join our +2M
This is your last free member-only story this month. Sign up for Medium and get an extra one
monthly readers.

Follow

Factories Are STILL Better Than


286 11
Classes In JavaScript
Updated thoughts on why you should use factories instead of classes
in JavaScript

GreekDataGuy Follow

Nov 24, 2020 · 4 min read

Photo by Pixabay from Pexels

After writing, Why factories are better than classes in JS, I got a ton of
feedback and corrections.

Let’s take this opportunity to dig into those suggestions, for my own
knowledge, and for the benefit of anyone new to JavaScript.

Consider this a rebuttal and extension of the original post.

Public properties on class instances present a


security concern (and how to avoid it)
Codepen 1.

I originally proposed that JS class instances were vulnerable to properties


being changed from the outside, and considered this a disadvantage.

For example, given a class, Car , we create an instance with new , and call
the drive method.

class Car {
constructor(maxSpeed){
this.maxSpeed = maxSpeed;
}
drive(){
console.log(`driving ${this.maxSpeed} mph!`)
}
honk(){
console.log(`honk!!!`)
}
}

const car1 = new Car(120)


car1.drive()
#=> "driving 120 mph!"

It’s “driving 120 mph!” . So far so good.

Public properties and functions can be changed after initialization


Not only can object properties be changed, those changes also affect the
output of methods.

car1.maxSpeed = 300
car1.drive()
#=> "driving 300 mph!"

Even whole methods can be overwritten.

car1.drive = function(){console.log('parked')}
car1.drive()
#=> "parked"

Editing properties and methods from the outside seems like undesirable
behaviour in most cases.

To be fair, this is how JavaScript was intended to behave. But that said,
intended behaviour doesn’t always equal “great” or ideal behaviour.

There are strategies to prevent changing properties


Codepen 2.

One suggestion was to prevent changing values by using a “getter” function.

class Car {
constructor(maxSpeed){
this.defMaxSpeed = maxSpeed;
}
get maxSpeed(){
return this.defMaxSpeed
}

drive(){
console.log(`driving ${this.maxSpeed} mph!`)
}
honk(){
console.log(`honk!!!`)
}
}

Notice we’ve added get maxSpeed() . The object will now be initialized with

a this.defMaxSpeed property rather than a this.maxSpeed property.

This prevents an altered maxSpeed from affecting the drive() method.

const car1 = new Car(120)


car1.drive()
#=> "driving 120 mph!"

car1.maxSpeed = 300
car1.drive()
#=> "driving 120 mph!"

That said, we can hack around this by updating defMaxSpeed from the
outside.

car1.defMaxSpeed = 300
car1.drive()
#=> "driving 300 mph!"

I suppose we could come up with a complicated property name that isn’t


guessable, but that would also make coding less fun.

Class instances suffer from scope confusion


associated with “this” (and how to avoid it)
Codepen 3.

For those new to JavaScript, the “this” keyword can be confusing.

Below is an example where calling $(‘button’).click(car1.drive) returns:

=> “driving undefined mph!”

Rather than the expected “driving 120 mph!” .

The cause is that this in this.maxSpeed no longer refers to the instance itself.

//////////
// html //
//////////

<button>Drive</button>

/////////
// css //
/////////

button {
cursor: pointer;
appearance: none;
border-radius: 4px;
font-size: 1.25rem;
padding: 0.75rem 1rem;
border: 1px solid navy;
background-color: dodgerblue;
color: white;
}

////////
// js //
////////
class Car {
constructor(maxSpeed){
this.maxSpeed = maxSpeed;
}
drive(){
console.log(`driving ${this.maxSpeed} mph!`)
}
honk(){
console.log(`honk!!!`)
}
}
const car1 = new Car(120)

Of the 3 different ways to trigger drive() on a button click, only the last
feels straightforward.

$('button').click(car1.drive)
$('button').click(car1.drive.bind(car1))
$('button').click(_ => car1.drive())

#=> "driving undefined mph!"


#=> "driving 120 mph!"
#=> "driving 120 mph!"

My original thought was to use factories to skip “this” entirely, but it turns
out there is an easy way to solve the scope issue with “this” and classes.

This can be solved for classes with the arrow function


Codepen 4.

class Car {
constructor(maxSpeed){
this.maxSpeed = maxSpeed;
}
drive = () => {
console.log(`driving ${this.maxSpeed} mph!`)
}
}

const car1 = new Car(120)


$('button').click(car1.drive)
#=> "driving 120 mph!"

Notice how the problem was solved by swapping drive(){...} with drive =

() => {...} . The button click now works with

$(‘button’).click(car1.drive) .

From my point of view, this seems like a great solution.

There IS an additional memory cost to factories


This is irrefutable.

Class instances have a smaller memory footprint. That’s because each


unique method only exists once — on the class prototype.

In contrast, factories create a copy of each method on EVERY SINGLE


instance. This becomes clear when we look at a factory.

const Car = (ms) => {


const maxSpeed = ms

return {
drive: () => console.log(`driving ${maxSpeed} mph!`),
}
}

Here the factory returns an object with a function inside it. Every object will
have that same duplicated function inside it.

This could use up a significant amount of memory if you were instantiating


10k+ objects (I wish there was a simple way to test this).

That said, I’m skeptical how often we need to generate 10k of the same
object in a browser during day-to-day development.

Factories and classes are not an apples-to-apples


comparison
I compared classes with factories, but that’s not completely fair.

They are 2 different “things”, from 2 different coding paradigms.

Factories follow the functional programming paradigm and are purely


intended to instantiate objects (instances or classes).

Classes follow the object oriented programming paradigm and are literally
templates for objects.

Another argument I’ve already alluded to is that all “problems” with classes
are simply the way the language was intended to work.

Conclusion
As someone new-ish to JavaScript, I do find factories simpler and less prone
to side effects.

While this may be due to a lack of understanding and experience, I’ve


always felt we should err on the side of simplicity over performance. Why
shouldn’t coding be beginner friendly?

If you disagree or can add anything here, I’m all ears for feedback!

And as always, keep coding!

Sign up for Last Week in Plain English


By JavaScript in Plain English

Updates from the world of programming, and In Plain English. Always written by our
Founder, Sunil Sandhu. Take a look.

Get this newsletter

JavaScript Frontend Coding Software Development Web Development

286 11

WRITTEN BY

GreekDataGuy Follow

Just a developer. Contact: greek.data.guy “at” gmail.com

JavaScript in Plain English Follow

New JavaScript and Web Development content every day.


Follow to join our +2M monthly readers.

More From Medium

Getting started with How to Send CSV Files Example of tree data Creating and Integrating
TypeScript for Node With Nodemailer structure Design Systems with
Bart Wijnants Zubair Ahmed in The Startup Ahmed Yagoub
StencilJS
Giancarlo Buomprisco in The
Startup

How To Build Your First Building a React Native Signal-cli using javascript HACKBACK Write-up
App With Electron Chat App — Part One: Pavol Travnik Shubham Ingle
Carol-Theodor Pelu in
Basic Messaging |
BucharestJS
PubNub
Krissanawat Kaewsanmuang

Learn more. Make Medium yours. Write a story on Medium.


Medium is an open platform where 170 million readers come Follow the writers, publications, and topics that matter to you, If you have a story to tell, knowledge to share, or a
to find insightful and dynamic thinking. Here, expert and and you’ll see them on your homepage and in your inbox. perspective to offer — welcome home. It’s easy and free to
undiscovered voices alike dive into the heart of any topic and Explore post your thinking on any topic. Start a blog
bring new ideas to the surface. Learn more

About Write Help Legal

You might also like