View profile

10 Things I Hate About JavaScript

10 Things I Hate About JavaScript
By Mastering JS Weekly • Issue #47 • View online
Don’t get me wrong, I love JavaScript. I’ve spent virtually my entire professional career, from my dorm room startup days on, building web applications with JavaScript. And even when I was writing Go, C, or C++, I always found myself thinking “this sucks. Why can’t I do this in JavaScript?”

What my old bosses probably thought I sounded like
What my old bosses probably thought I sounded like
But, contrary to what the “do what you love” crowd might think, just because I love JavaScript doesn’t mean there aren’t days when I want to throw my keyboard out the window and move to a place that has no internet access.
Here are some of the things I dislike most about JS:
10. Deep Equality Comparisons
Comparing two objects in JavaScript is extremely nuanced. Given 2 values, there are 4 ways to compare them for equality in JavaScript. And that’s just shallow equality. Determining whether 2 different objects (objects that are not `===` each other) contain the same data is even more confusing:
  • Which shallow equality algorithm do you use to compare object values?
  • Do the objects need to have the same prototype?
  • Is `{ a: 1, b: undefined }` the same as `{ a: 1 }`? What about if `b` is a property on the prototype?
The problem is easier if you limit it to POJOs, but then what about libraries like Immutable.js that are meant to be wrappers around POJOs?
9. Frontend/Backend Split
I think JavaScript’s 2 biggest inherent benefits are the event loop and the fact that almost every device has a JavaScript interpreter in the form of a web browser. Using the same language to develop both the trusted environment portion of an app (backend) and the client portion of the app (frontend) is an amazing benefit, especially since the entire internet already has the tools to run the client portion.
On the other hand, there’s been some pushback against the idea of full stack JavaScript, particularly since 2015-2016. The prevailing meme seems to be that frontend JavaScript is already “too complicated” and there’s no way anyone could possibly have the mental capacity to work on both frontend and backend.
Is frontend or backend too complicated to do both? It depends on the situation. In an established company where there’s a lot of specialized complexity in one side or the other, perhaps. In a greenfield project, you should be able to do both frontend and backend.
8. Bundling/Compiling
At my first day job, there was one awful piece of client code that took at least 45 minutes to recompile. Working on it was impossibly painful, because even the smallest one-line change took hours to test. Learning how to work effectively with it took months.
Using bundlers and compilers like Webpack isn’t wrong. Sometimes it is the right way to go. But just be aware that compilers often break existing code because not all projects are built for, or even aware of, the conventions that tools like Webpack rely on.
7. Event Emitters
Event emitters are a pattern for allowing two distinct modules to communicate without explicitly depending on each other. Unfortunately, there are a couple of key weaknesses: if you `emit()` an event and the event handler throws an error, the code that calls `emit()` gets an error. Also, Node’s built-in event emitters don’t have a way for you to listen to all events, making it hard to discover new events or understand the flow of events as a whole.
6. typeof null === 'object'
The fact that the `typeof` operator reports that `null` is an object has caused an infuriating amount of bugs. This behavior unfortunately makes checking “is the given value is an object that you can set properties on” a two step process.
5. NaN !== NaN
An unfortunate wat that I still find baffling. JavaScript has 4 ways to check for equality between two values, and 3 of those are only different in how they handle NaN, +0, and -0.
4. typeof NaN === 'number'
For all of NaN’s special cases, NaN is still technically a number. It’s just a number that doesn’t strictly equal itself. On the bright side, at least mathematical operations don’t throw an error when they encounter NaN.
3. Mutable Globals
One of my favorite things about JavaScript is that everything is a variable. You can instantiate, assign, and return classes and functions as easily as you can strings and numbers. Unfortunately, that also applies to global variables, and developers often abuse that to overwrite global functions like `require()`, or add methods to array prototypes.
Real code generated by Webpack trying to compile the npm package "formidable"
Real code generated by Webpack trying to compile the npm package "formidable"
This leads to all sorts of nasty surprises. Like how recent versions of Mongoose don’t work with Sinon’s `useFakeTimers()`, because `useFakeTimers()` overwrites the global `setImmediate()` function. Overwriting global variables is one of those things that all developers know they “shouldn’t do”, but many end up doing it anyway because it can be more convenient.
2. Binary Floating Points
0.1 + 0.2 !== 0.3 in JavaScript. Unfortunately this isn’t limited to just JavaScript, most scripting languages have the same issue. But given that JavaScript now has BigInts, it seems surprising that there isn’t much of a push to add decimal floating points to make arithmetic more consistent.
1. Async Stack Traces
I’m sure every Node.js developer has seen a stack trace that ended with the below code, and ended up having to carefully read the code to figure out what happened.
Ugh.
Ugh.
Async stack traces are becoming better supported: both Chrome and Node.js now have support for async stack traces. As long as you’re only calling async functions, you’ll get a coherent stack trace that shows your function calls, rather than Node.js internals.
However, async stack traces are still hard to work with, because the instant you use a library that does async without async functions, you lose async stack traces. Hopefully in the future, async stack traces will be easier to work with, because they make it so much easier to debug production issues.
That’s 10 things I hate about JavaScript. The number 1 thing I love about JavaScript is all of the excellent tools and frameworks out there that make developing web applications so much easier. Mongoose is one of our favorites and part of our recommended stack. Check out our new eBook, Mastering Mongoose, and become a full stack Mongoose expert today!
Most Recent Tutorials
Get The Current Array Index in JavaScript forEach() - Mastering JS
JavaScript Array `includes()` - Mastering JS
JavaScript Append to Array - Mastering JS
Using Axios' Proxy Option - Mastering JS
Other Interesting Reads
.css-1jpgufy{color:#212121;box-shadow:none;}.css-1jpgufy:hover{opacity:0.8;}Harry Wolff
Webpack 5 release (2020-10-10) | webpack
Did you enjoy this issue?
Mastering JS Weekly

A weekly summary of our tutorials

If you don't want these updates anymore, please unsubscribe here.
If you were forwarded this newsletter and you like it, you can subscribe here.
Powered by Revue