Tuesday, March 17, 2015

Four Solutions to the JavaScript Problem

If you have worked with JavaScript, you are surely familiar with a long litany of complaints about the language. Some developers are frustrated by its very loose, dynamic nature, while others point to odd behaviors such as hoisting and conversion-on-equality as big problems. (More here.)

I don't want to belabor the problem itself; plenty has been written about that already. Instead, let's consider the solutions. There are essentially four types, at increasing distances from plain JavaScript.


Use JavaScript Carefully: Program in JavaScript directly, but avoid or work around the sharp edges of the language, such as weak typing and the lack of a module system. In effect, you program in a restricted sub-language of JavaScript. This is what Douglas Crockford and Stoyan Stefanov advocate in their books. Crockford goes even further with JSLint, a verifier that strictly enforces the use of his dialect of JavaScript. 

Add Annotations: Add hints about the programmer's intent to the code, typically with type annotations. This requires a compiler to process the language, but both the input and output languages of the compiler are JavaScript -- perhaps even identical to the input if the annotations read as comments in JavaScript itself. This is much of what TypeScript and Closure try to do, although their compilers go a bit farther, adding things like a module system.

Use a Neighboring Language: Program in a fundamentally different language than JavaScript. But keep the data model and functionality close enough that translating to JavaScript isn't too hard. With a small semantic distance, the output is recognizably similar to the original code, making it useful for debugging. CoffeeScript and PureScript follow this model. 

Use Something Else Entirely: It is possible to compile virtually any programming language to JavaScript, although more distant languages require a lot of extra JavaScript code output to bridge the semantic gap. And of course more code means more execution time. Kiss source-level debugging goodbye too. GWT and Haste do it this way.

Where you want to be on this continuum depends on how troublesome you find JavaScript and how much control you are willing to hand over to a compiler and runtime system.