Survival Guide on Javascript (for the Elm Developer)

So you’ve been asked to do something in Javascript. Does this mean you will have to leave your utopian, safe-yet-powerful Elm world? Well, yes. But remember the advantages of Javascript. It blends data and code in a somewhat dirty but (at least with recent updates) pragmatic way. It is concise. It can be functional or prototypical (or pretend to be object orientated). Libraries exist to do everything (even if you have to use at least 30 to do anything). You can make single page apps, native mobile apps, backends, database queries, IOTs and more with it. And it is rapidly improving (see async/await, safe access operator and so on). Actually, I really like Javascript and particularly for smaller projects it is likely to be my first choice.

The Survival Tips

Elm like many functional programming languages leverages pattern matching for clear, concise code which deals with all possible cases. Javascript has a C-style switch statement. Yeah, the one with the ridiculous and counterintuitive fall through (you must return or break; otherwise the next statement will also be applied). The one that might not be exhaustive. It is awful. But to make it a bit less worse you should always add a default statement at the end along with a console.error, logging whatever unexpected input you provided.

Runtime errors are a thing. In React 16 you can now at least isolate them with a new componentDidCatch lifecycle method. Use this for major pieces and at least the damage is limited. Log things. Expect the undefined.

Keep things as simple as possible. But where in Elm I might add ‘but no simpler’ in Javascript err on the side of too simple. Who knows maybe they didn’t really want that feature?

Unlike Elm, where it is possible to make sweeping structural changes fearlessly, in Javascript this is likely to be extremely painful. Try to get the architecture right from the start. This may mean erring on the side of more structure, more verbose and explicit libraries (e.g. Redux). Though if you try to write in a fairly functional style with libraries like React things are unlikely to be too bad. If you write jQuery and keep adding more functionality to a page things will get probably get really messy. Components can simply be deleted and replaced with better versions when you know they are actually valuable.

Use Flow for type checking. It can do somewhat similar things to Elm, though sadly it is way more verbose and harder to work with. It has pretty good editor integration (set this up). Also try to get this in place early because trying to introduce it to a large existing project is not going to be fun. It works well with React (although the way this works has changed repeatedly).

Testing is a lot more important in Javascript. Although the frameworks to do this are actually really pretty good (and fast compared to most languages). See Jest (the ‘Facebook’ option and one I’ve mostly used) or Ava (which has magical asset statements that give useful error messages, a bit like Elixir).

Keep your dependencies up to date. Things change rapidly and if you fall behind by even a few months you will have some painful catching up to do!

Learn vanilla Javascript. Understand this. Know enough of DOM API to do things like find elements and add classes. You should pretty much never actually create Apps this way, but it is useful to know. And be aware of the awful bits. The dreadful double equals. Inequality comparisons. Set your editor up to tell you off for using them.

Embrace Modern Javascript. It is becoming a really nice language (with some awful parts left in for backwards compatibility). Also I suggest using the latest stable version of Node. Because it actually allows you to write modern Javascript in the console and without transpilation.

Embrace the runtime tooling. All modern browsers ship with extensive tooling around Javascript state, debugging and performance.

Extract complex business logic into (externally) pure functions, ideally in separate files, which work with plain old javascript objects. These can be tested or replaced easily.

Concluding Thoughts

In the last few years I’ve created substantial Applications in Javascript, Elm, Swift, Python, Ruby, Kotlin and Java. The only language there I would reject outright for a new project is Java (because Kotlin is clearly better). The rest are great choices (in the right context). But none of the others has the reach of Javascript. Yes, it requires more discipline than most of the others. But to those who complain about its prominence, remember it could have been so much worse (PHP? Java applets?). But that is actually an unfair framing, as it holds up well to the best modern general purpose languages (Swift, Kotlin).

Undefined is not a function

Okay so actually it is probably better to say I’m extremely ambivalent about Javascript. It can sometimes allow such powerful things to be done so quickly and simply. And sometimes undefined is not a function. That seems like a good ending.