writings

Writing JavaScript without using ‘this’ and ‘new’

published on: Thursday, November 21, 2024

A while back, I saw a tech talk by Douglas Crockford on youtube where he talks about the new JS style he has been using. I first read JavaScript: The good parts nearly 10 years ago, and I’ve re-read it several times since then. It’s one of the best books on JS.

The talk is titled “JavaScript: The better parts” - likely referencing the book. In the video, he talks about a lot of the features of the JS language he has stopped using while writing code:

Then he switches gears and starts talking about a different topic. I found this part of his talk to be interesting, so I’m writing about it.

Three months ago, I had a chance to create a new project from scratch - A true greenfield project where I could do whatever I wanted to do. I decided to write this new project by following the rules which Crockford said he’s been following. To make this more concrete, I added the above to the repository’s styleguide and enforced this coding style by using a few linting rules, and by being thorough with the code reviews.

I also came up with a couple of my own rules for writing JS:

We did not run into any issues by following these restrictions. In fact, this style of coding made refactoring a breeze - we no longer had to think about how a function might be invoked - via bind or apply for instance. This forced us to define getters and setters (mutators) for every single field of our data models which needed mutations.

A lot of the time, we had to think hard about: “should outside consumers of this object be able to change this <field> or should it be a derived value based on the values of <field1>, <field2>, <field3> ? “ This made the overall code way better.

Defining everything as functions and exporting stuff using ES6 imports and exports meant mocking things was trivial. All the private data we needed access to had a public api, so we could refactor fearlessly without worrying about consumers.

One thing that was a little hard was to avoid using null completely. While we could avoid it entirely in our frontend code, some of the JSON responses sent back from the server were null values. To deal with this issue, we basically wrote a set of util functions that would deal with de-serializing the server responses and providing us well-formed client side objects(models) where there would be no nulls.

Along the way, I learned the real difference between null and undefined and the semantic meaning. I tried to look up the original author’s blog to link here, but it’s now lost amidst the SEO and AI-generated crap that has turned the internet into a pile of garbage. So I’ll summarize here:

  obj.something = undefined;
  obj = undefined;
  ...

or its variants.

However, having said all of this, we decided to use undefined in our code as the only sentinel value when representing that certain fields or properties had nullish values. This was done for the same reason that Crockford does it: in JS there is no way to avoid dealing with undefined, but you can avoid using null if you really want to.

A neat effect of composing our code this way was the amount of code coverage we were able to get as it was easy to test most of our functions + the public apis.

My code has had the fewest bugs in this project so far, and the average turn around time to fix bugs has been under a day (Of course, we also had a robust framework and good patterns for error handling and everything). It’s quite possibly the best JS/TS code I’ve written till date in the past 11 years.

I will definitely be following this style for the next set of projects I’m going to be working on.