A Reflection on Javascript Hate

Recently, while browsing a popular tech news site's comments, I stumbled upon a modern staple in the online tech discussion world: the javascript hate thread. I've blogged about this theme before but it's almost a trope at this point. User posts article, article involves javascript-related technologies, commentor reviles javascript, debate ensues, comment section now entirely derailed from original post.

However, this comment was particularly inflammatory where the user not only criticised the language but also attacked the entire ecosystem and went as far as decrying ALL users of the language as sub-standard programmers. Quite the blanket stament but, shockingly, I found myself attracted this argument. While I would never be so careless to criticise an entire group of people with one argument, as I read the debate I found myself leaning more towards the anti-js camp. I started to think about this sentiment and asked myself, why do I feel that way? I've used javascript a fair-bit and while I hold my share of opinions on the language and the ecosystem, I've never hated it. In the same way I've never hated a hammer. In the end it's just a tool. When I need a hammer, I use a hammer. When I need a screwdriver, I use a screwdriver. If my hammer is not good enough, I just get rid of it and go grab a hammer that suits my needs. I don't hate the old hammer. At least not enough to go online and tell everyone about how bad that particular hammer is.

One final comment on hammers. I don't buy the argument of "javascript is bad because we're forced to use it" since it is the only language natively supported by the browser. Akin to being forced to use a particularly bad hammer. As of 2020 this is just not true at all. There are many languages that now compile directly to javascript and serve as a different tool for the same job. With the advent of webassembly this is even more true.

So after reflecting on this issue for a bit, I've resolved my opinions and why I have a negative reaction to the javascript world. In my opinon, the real culprit in the equation is the browser and its hijacking of desktop computing.

Allow me to take a step back. Today, when using almost any programming language or tools we are going to be exposed to the decades of software history and legacy code that makes it all happen. I think this is true regardless of the level of abstraction, whether you're shunting data around registries in x86 or fighting with the linker or writing some python scripts. While our higher levels of abstraction might shield us from some of the underpinnings, they don't obstruct them completely.

For example, we see this with python starting from the first step. When installing, you must select the 32-bit or 64-bit interpreter installation file. Immediately you're exposed to the idea of "cpu architectures", even if you don't know what it means. You're then given an exe that will start an installer that asks you some questions about adding to PATH and installing to C:\Program Files\Python38. Here we are exposed to operating system conventions and file systems. You start writing your python script and now you want to build an interface, cue PyQt or Tkinter or something similar. These libraries are built on top of multi-decade old code while not exactly being spring-chickens themselves. Their APIs have evolved and shifted, reflecting the evolution of software over time and embedding hard-earned wisdom from years of experience and usage. While building the UI we're exposed to even more OS conventions, file/network IO, dialogs, graphics, sockets, and more. It's usually not long after a user has started writing their first program that they have to learn basic concepts of threading in order to not hang their GUI for a semi-intensive task.

So even for something as abstract as python we're not completely detached from the world below it. While python makes it easier to interact with those layers, it doesn't, and arguably cannot, hide them completely. This changes completely with javascript. More specifically, this changes completely with javascript in the browser.

Javascript evolved in a different world. While other programming languages operate in the world of the desktop/server operating system, javascript originally only existed in the browser. Up until the advent of node.js and the push for server-side javascript, the browser WAS javascript's operating system. Instead of making operating system syscalls javascript calls the browser api and, from the perspective of javascript, that is a syscall.

I think this is an important consideration on why javascript the language and ecosystem feel so fundamentally different from anything else. For a long-time it existed in a world where it could skip so many parts of what goes into a programming language and its ecosystem. Experiences that one might have had developing a native application simply dissappear when using javascript in the browser.

The software distribution story is solved so you don't need to think about packaging, native formats, cross-platform compilation, etc. Cross-platform UI is solved, target HTML + CSS and you can display what you want. Restrict your browser api usage or javascript syntax to the most widely supported variants and your code will run on nearly any browser. While web developers often complain about "cross-platform" inconsistencies across browsers I think they'd be outdone by os gui toolkits (win32, gtk, qt, cocoa, etc.) and graphics apis (gdi, opengl, directx, etc.). Threading? File permissions? File IO? For the majority of javascript development all these concepts don't exist, and don't need to exist.

Except, as more is demanded of javascript in the browser, these things need to exist because they are fundamentally useful. In response to demand for more rich experiences in the browser we can see in real-time how the browser becomes more-and-more like an operating system. For example, we now have workers for multiprocessing work. A binary execution model with webassembly. 2d and 3d drawing APIs (canvas and webgl). Audio APIs, location APIs, mic/camera APIs, websockets, localstorage, etc. with more being added all the time.

So what's the implication? Well, if the browser is the OS then everytime you write javascript you are writing "native" code with respect to the environment. If calling a web browser api is akin to calling an operating system api, then writing C++ for a desktop OS is conceptually the same level of abstraction as writing javascript for the browser. Except, when writing javascript for the browser, since it's fundamentally a completely different world, we have to do it all from scratch in a language that wasn't originaly designed for that purpose. We can't leverage the decades of libraries and tools already available because they were written for a different kind of operating system, a different world. We can't transfer the decades of experience and wisdom learned from developing for the desktop and server because some of the most basic primitives from the old systems are only in their infancy in the browser world or don't exist at all. With javascript, you have to throw it all out and start from the beginning because the browser does not allow it to happen in any other way.

I believe this is what essentially drives the negative attitude towards javascript by experienced developers. This alientation of the entire software world by the javascript and browser ecosystem. It's entirely frustrating to see years and years of cummulative iteration and development replaced by a new system. The fact that the new system is ultimately worse than the old system is the most tragic part of it all. We threw out all the old paradigms and rebuilt them from scratch but worse. This is what frustrates me the most as a practioner and observer. Not trivial matters like left-pad or language oddities but the real issues. Such as, despite the fact that web development has an amazingly sophisticated developer experience it still does not deliver the same user experience as a well-crafted native application.

So it's easy to hate. It's new, it's not better and it has a lot of problems. It's constantly changing and it's unpredictable. Things are being rewritten from scratch and they pale in comparison to their predecessors. It's easy to criticize the system and it's easy to criticize their practioners. Resources are taken away from the old system (tried to build a desktop app lately? -- hah) and dedicated to the new one. Every year there are more and more javascript developers, javascript jobs, javascript libraries and tools. Browsers are growing and getting more complex as they start to outpace operating systems in line count and, eventually, features. We're in this limbo phase, where the old system is neglected but the new one is not ready for us to jump full force into. We're like the customer of a v1 product while the company is working on v2, or like an older sibling watching our younger sibling get all the attention. It's not great and it's probably going to be rough for a while longer.

Despite all this I am optimistic. I think things will improve but since we're still in the early stages it's easy to hate. It's hard to forget this is essentially a rewrite of the system and we haven't even reached feature parity yet but the future looks interesting. Especially things like webassembly are exciting. To me it signals the beginning of bridging the old world and the new world. Seeing all these desktop applications being ported to the web signals to me we're entering a new era of compatibility where we'll be able to bring with us all the good parts of the old system and leave behind the kludge. Where, when the javascript virtual machine inevitably takes over as predicted by Gary Bernhardt, things will be, in fact, better.