endJS

Donald Knuth has been famously quoted as saying "premature optimization is the root of all evil". That's because he'd never tried JavaScript...

JavaScript has been the most popular programming language in the Stack Overflow Developer Survey for 12 years in a row (as of 2024). Why is this? Is it because it's well designed? Or because it's fast? Well... no. JavaScript is one of the most poorly designed programming languages, and is individually responsible for wasting an incomprehensible number of human hours producing terrible software which has ultimately trained the average user to think their computer is way slower than it actually is.

Why is JavaScript Bad?

I can give a long list of features and design decisions of JavaScript which are absolutely terrible, but I think the horror of JS is best shown by giving examples of actual programs and algorithms, to show where these things actually show up.

== Doesn't Check Equality

Let's start with a simple one. a == b can be true, with a and b being obviously different things. Here are some examples of equality checks, all of which are true:

[] == false
'' == false
'2' == 2
1 == true
0 == false
'0' == false
null == undefined

Now it can be argued whether pointer equality or deep equality should be used in a programming language, however at least in those cases the rules are consistent and clear. The JS standard which describes how == should work is an absolutely absurd list of 14 rules with sub-rules, which in turn reference complicated type conversion functions. This is a classic example of the fact that because the way that JavaScript interprets so many simple, single lines of code is so deeply unintuitive, you end up spending more time debugging your understanding of the language than you do actually writing code.

If you've never programmed in JavaScript before this will seem crazy. But so many people, even those who hate JS, have had to program in it enough that the Stockholm syndrome starts to sync in and they forget just how moronic of a design decision it is to have the equality operator not check equality.

Function Argument Permissiveness

The combination of first class functions with an extremely dynamic type system lead to some interesting points of frustration when programming. Let's say you write a simple function which adds the first n natural numbers together:

let naturalNumberSum = function(n) {
    let sum = 0;

    for (let i = 0; i <= n; i++) {
        sum += i;
    }
    return sum;
};

but very quickly realise that you need to generalise this function to accept a lower bound other than zero, for example to calculate the sum of all natural numbers between 10 and 20 inclusive, so you make the appropriate changes:

let naturalNumberSum = function(lower, upper) {
    let sum = 0;

    for (let i = lower; i <= upper; i++) {
        sum += i;
    }
    return sum;
};

Great, now you can use the function to calculate the desired value:

naturalNumberSum(10, 20)

Except what about all the cases where you've previously used the function for its old purpose. In any language with proper static type checking, each of these instances would be a compiler error which can be systematically fixed, changing naturalNumberSum(x) to naturalNumberSum(0, x).

In JavaScript though, the function gets called just fine with what was previously bound to x as lower, and upper as undefined. So we have to deal with some strange runtime error because upper is undefined right? Well no, JavaScript's permissiveness of undefined values means the function actually runs just fine, it just gives us the wrong output:

> naturalNumberSum(10)
0

thus leaving a bunch of nefarious bugs which we have to carefully and diligently hunted down.

A more experienced JavaScript programmer would probably solve this problem by having special checks for when upper is undefined, and doing a sort of runtime polymorphism as follows:

let naturalNumberSum = function(lower, upper) {

    if (upper == undefined) {
        upper = lower;
        lower = 0;
    }

    let sum = 0;

    for (let i = lower; i <= upper; i++) {
        sum += i;
    }
    return sum;
};

Not only does this make our code much harder to read, we actually now need to worry about the implications of our upper == undefined statement evaluating to true in undesired cases, such as if upper is null.

So when any other language would prevent this problem at compile time, and potentially even allow the statically checked overloading, JavaScript forces us to write harder to read and more error prone code.

Approach to Incorrect Code

JavaScript has decided that rather than deal with errors and help the programmer correct them, it is better to ignore them and pretend they don't exist. This is through turning what would be compilation errors in other languages into runtime or logic errors.

Let's say you have an object which stores a boolean field on it:

let person = {
    firstName: "John",
    lastName: "Doe",
    age: 52,
    deceased: true
};

and at some point in your program you wish to do some logic depending on that boolean field:

if (person.deceaced)
{
    // do something
}
else
{
    // do something else
}

Note the typo in the condition of the if statement. What happens when I make this mistake in C, C++, Rust, Java, Swift or Go for example? The compiler tells me. It explicitly states that the field does not exist. What do Python and R do? Well you have to wait until the interpreter hits that line to identify the error, which is not quite as good, but at least you still find out. What does JavaScript do, well because it didn't statically check the types ahead of time it just treats person.deceaced as undefined. This means we are evaluating if (undefined), and because undefined is falsy (i.e. it coerces to false), the else case runs, even though our field is true. So here, a typo causes not a compiler error, not even a runtime error, but a logic error.

Now this example may seem simple to fix, but it's not when you've got a codebase of thousands of lines, or you're using a field on an object returned from a library, and you haven't quite capitalised the name correctly because it uses a different styleguide. This means when programming you have to constantly check these minor things.

And no, powerful linters in editors are not an acceptable solution to this problem. The web developer mentality of just adding a band aid fix to everything which is bad because it was designed poorly is what causes so many of these issues to begin with.

This is one of many examples of JavaScript's allergy to compile and runtime errors, along with its aggressive type coercion and permissiveness around undefined values particularly with function arguments, which dramatically slow the software development process and introduce countless logic errors.

More Examples of JavaScript Being Terrible

If you have yet to be convinced that JavaScript is poorly designed, here is a collection of examples of showing off the many reasons why JavaScript is terrible:

The Broader Issue

JavaScript is not just bad because it's a poorly designed language, it represents a direction the software industry as a whole is taking, moving towards software with so many layers of abstraction that make it impossible to reasonably predict the performance of a program. So often these new fancy tools are created to improve so called "developer productivity", but end up reducing software quality. Think about how many UI frameworks there are for JavaScript, some built on top of others. Have any of them really solved the core problem?

Most web developers simply cannot conceive of how fast computers can be, because their language is slow, their tooling is slow, their industry rarely makes performance a requirement, and any attempt to make their code fast may result in them being shot in the foot because of hidden behaviour of the web rendering engine.

The worst thing though is that most people don't see this as a problem.

Most people don't seem to put two and two together when game developers can reliably render 60 different high definition images a second whilst tracking the state of thousands of objects, yet discord takes 5 seconds to start up on a computer with a 16 core 12th generation i5 and 32 gigabytes of ram. Because rather than just draw pixels on the screen, when your computer runs a JavaScript app like Discord, it's reading the source code while running it, in this hugely complicated browser engine, while manipulating this additional UI abstraction called the DOM. All while making sure to render things correctly given a separate text based document call CSS.

And this is not just a user experience issue. Software written in JavaScript regularly executes thousands of times the number of CPU instructions necessary to complete the relevant task, which equates to thousands of times the power consumption, and thus green house gas emissions. With all the software in the world written in JS, the greenhouse gasses emitted by computers running way more instructions that necessary becomes seriously non-trivial. So yes, I am going to be that guy who makes the "JS is destroying the planet" argument.

The 7 Step Plan to End JS

So, I now present a 7 step plan to put an end to JavaScript.

1. Stop promoting JS as "beginner friendly"

Turning a single character typo into a logic error is not beginner friendly. Not warning the programmer when they try and add a number to a string is not beginner friendly.

Programmers who learn JavaScript as their first language are taught a number of bad habits that are extremely difficult to give up later on. Moreover, they gain no appreciation for what their computer is capable of, and how it works, and not having true predictability about performance of code makes teaching good algorithms extremely difficult, so much so that web developers generally don't bother. Learning to write fast code for the web is not about learning algorithms, or how computer hardware works, but rather learning how to manipulate the browser engine in unexpected ways to write the slow looking code that's actually optimised in an unexpected way.

The way to put an end to JavaScript starts by stopping promoting it to future generations of programmers. Wouldn't we rather train new programmers to write high quality, fast software that meaningfully improves the way the end user interacts with their computer, instead of sending more optimistic and bright new software engineers into internet companies whose services haven't significantly changed in years despite the number of new developers they hire.

2. Stop pretending like typescript solves the problem

None of the runtime benefits from already having checked types are available in typescript, because it compiles to JavaScript anyway.

Typescript is just an excuse to continue using JavaScript, which allows people who quite reasonably can't stand dynamic typing, to be able to reasonably write code for the web. It doesn't solve the problem, it pushes it back, and allows JS to live for longer than it should.

3. Stop using JS for command line apps

JavaScript was built for the web, not for the command line, and it shows. It seems like every JavaScript program written for the command line is absurdly slow, and it's not always clear if this is because JavaScript has trained incompetent programmers, or the language they use is really that slow. Some notable examples I have come across are sfdx and the Netlify CLI, the former of which I have found can take up to a second to display its help page.

4. Stop using JS for desktop and mobile apps

While the most well performing desktop software is usually written using low level graphics libraries like OpenGL, one does not have to use such libraries to be able to build robust, good GUI apps, that are at least leagues ahead of what people are doing with their bundled browser engines.

One of the frequent arguments for frameworks like Electron is just how easy it is to use. In the current state of the software industry, it seems like programmers are too afraid of doing anything themselves, or putting any work into making things good. As a consequence, most developers create apps by hacking together a combination of a few high level libraries that they don't understand, with so many layers of abstraction that result in software which is absurdly slow, and has bugs that are nearly impossible to trace. The thing is though, developers not wanting to use anything other than a high level JS library is a self fulfilling prophecy, encouraging the further development of these libraries which are doomed to fail if you care about quality software.

5. Stop optimising hardware and software for JS

Trying to make JavaScript fast is like trying to make reading Shakespeare enjoyable, it's truly an uphill battle, and yet countless people have dedicated their PhD theses, and in some cases their career, to working out ways of making JavaScript not run like crap. Think about how much more mature the tooling for building web apps in lower level languages would be if those people instead devoted their time to working on WebAssembly.

6. Stop using JS for web apps

People are going to say "but what else is there?" And while it is true that because the web is designed to work with JavaScript most of the current tools are built for JavaScript, there are an increasing number of alternatives.

If you want to compile to WebAssembly from a decent programming language, then this list on the official WebAssembly website has details on how to do so from many such languages.

There is one important thing to note though. These tools only get better if people use them. If you want high performance software for the web, then these are the tools to invest your time into, and using them is the only way out of the JS nightmare we all live in.

7. Stop supporting JS in browsers

Imagine if tomorrow, one of the major browser engines announced that it would no longer be supporting JavaScript in a decade. Think about the Manhattan project that would motivate to produce high quality, well performing tools which target web assembly for web development.

Now, if anyone is going to do this, it's going to be Apple with WebKit. If there's any company that truly doesn't care about stepping on some toes and making people angry in order to force the industry in a particular direction, it's Apple. Soooo, maybe a bit of a campaign to start there...

Further Reading

I, the creator of this site, am not the only one who hates JavaScript, and this is not the first piece of online material dedicated to the case against JS, so here are some other great blog posts, articles and videos about why JavaScript is bad, how to live without out, and the problems with the current state of web development: