coffeescript => es6
I've been using CoffeeScript for most of my development work since 2011. In general I appreciate the language's brevity and features (most of which keep you from shooting yourself in the foot).
With the rising popularity of ES6, I decided to read Axel Rauschmayer's excellent book and take it for a spin with some of our new projects. Listed below are my initial impressions after having written a couple of thousand lines with it.
Variable Declarations
ES6 comes with a ton of features which are not supported in CoffeeScript, such as maps, sets, symbols, generators, and promises. However, I've found that let
and const
are profoundly important. Having block-scoped variables removes a significant number of potential gotchas in JavaScript. const
, in particular, provides both a write lock and a visual cue that's compelling. I use it everywhere I can in our code.
Modules
I haven't yet experimented with modules, as they aren't available in meteor 1.2. However, with 1.3 and beyond, the module syntax will enable the build system to make substantial optimizations including dead code elimination and lazy loading. In other words, once meteor understands how your modules are connected, it can do things like ship smaller binaries and load your code only as needed.
None of these optimizations exist at the time of this writing, but their potential is game changing. Although CS doesn't have ES6-style imports and exports, meteor will be supporting the feature via CommonJS-style require statements. [1]
Punctuation
CoffeeScript is concise and JavaScript is, comparatively, verbose. My biggest concern about this switch was that I'd end up writing many more parens and curly braces. While this is true, I'll say there is something liberating about knowing exactly what my code is doing without having to periodically paste snippets into a transpiler. For example, does subtractNumbers 12, addNumbers 5,7
actually do what I think it does?
Surprises
Even though ES6 was heavily influenced by CoffeeScript, some syntax features didn't make the cut. Here are the two most glaring omissions:
Existential Operator
In CS, we have the existential operator ?
, which lets us write x?
instead of
. It's 2016, and we still don't have a suitable shortcut for testing existence in JavaScript, which is just absurd.
typeof x !== "undefined" && x !== null
Arrow Functions
ES6 gave us "fat arrow" functions, but deliberately left out "thin arrow"functions (those which don't give you a lexical this
). While this solves some annoying issues in JS, it introduces the opposite problem where programmers blindly replace function
with =>
and end up binding the wrong context. When the ecmascript
package became available in meteor 1.2 there was a continual stream of questions on StackOverflow related to this misunderstanding.
You may be asking, "but don't you want a lexical this
the majority of the time?" As it turns out, a linted CoffeeScript codebase provides the perfect answer to this question: no. At Edthena, 98% of the time we use ->
.
Linters
In the past year, we've made heavy use of CoffeeLint, which has been an adequate way to enforce style throughout our codebase. Using a linter with CoffeeScript is nice, whereas with JavaScript it's a necessity because of the potential for leaking global variables (among other things).
The good news is that some combination of jscs and eslint can provide you with solid protection against yourself. The bad news is that you need to have a Ph.D. in eslint in order to configure it. Have a look at the one from mantra's example app here. Yikes.
Final Thoughts
Overall I enjoy writing in ES6 more than I thought I would, and it's nice to use the same language as everyone else when posting publicly.
My initial concerns over having a punctuation explosion in our code have been somewhat alleviated by using a decent editor. For those using atom, I'd recommend the jscs linter which can auto-correct your style blunders when saving.
Best of luck to anyone making the switch. Feel free to post a comment and tell us how it's going.
[1] Thanks to Loren Sands-Ramshaw for pointing this out.