Is CoffeeScript still relevant or is it a has-bean?

After publishing my piece on Promises, a number of people pointed out the I had forgotten to return a value in a .then() function. Unforgivable, of course, but my excuse is that I’m more used to programming in CoffeeScript where the returns just happen automatically.

So what is CoffeeScript?

CoffeeScript is just Javascript with a much simpler syntax. Everything you write in CoffeeScript, you could have written in Javascript. It is a preprocessor. It gets rid of (most of) Javascript’s braces by using indents so where in Javascript you’d write:

var square = function(x) {
return x * x;

in CoffeeScript, you’d write:

square = (x) ->
x * x

Ah, I hear you say, an arrow function. But now we have arrow functions in ES6 so why bother? Well the thin arrow -> in CoffeeScript is the same as the fat arrow => in ES6 functions and you may or may not appreciate the lack of braces. The fun really starts when you start looking at the fat arrow => in CoffeeScript. This really comes into its own inside classes. CoffeeScript classes are very like ES6 classes: here’s an example from a piece of production software. It’s just a snippet from a base class. @ simply means this or this. — one of CoffeeScript’s many shorthands.

class Table
  constructor: (@params) ->
  store: ->
.then ->
.then (dbh) =>
sql = "
dbh.query sql, [ @table, @params ]

Let’s look at the arrows in turn. Each defines a function. The constructor is a simple CoffeeScript shorthand which sets this.params = params, where this relates to the class. The thin arrow after store: creates a function on the prototype of Table so this relates to our class.

Now let’s take a look at our two .then functions: the first doesn’t care about this as it doesn’t use it. But the second one, .then (dbh) cares very much. It needs to pass this.table and this.params to the database query where this refers to the class, not the current function.

Without CoffeeScript, we’d probably have resorted to using var that = this or similar but our fat arrow has taken care of it for us. And remember the comment about getting automatic returns? Well CoffeeScript happily returns our Promise to the store() call and the last thing we mentioned in each of the .then() functions.

Is that all?

Is that all we get from using CoffeeScript? A fat arrow similar to the ES6 arrow? Not at all. Look at some more snippets from real code:

params[key] = val for own key, val of @ when key of @fieldset

This shorthand iterates through the properties of our class and checks for real (not prototype) properties using hasOwnProperty(). Then it checks if the property is also a property of this.fieldset and, if so, adds it to the params object.

Remember automatic returns? Pretty much anything returns a value, so you can do things like:

# Get the result of an if statement
result = if rows.length is 0 then null else new @ rows[0]
# Or of a switch statement
per = switch customer.frequency
when 'monthly' then 'month'
when 'annually' then 'year'
else 'quarter'
# Or of a for loop
files = (for file in files when not file.match /^index/)

My favourite language of choice before CoffeeScript was Perl. In other languages, I really missed string interpolation, function calls without parentheses, post-fix if and unless and simple testing for undef. Here’s a snippet of real CoffeeScript code that uses them all:

return callback error: "User #{username} not found" unless user?

Javascript would require something like the following (which is what the CoffeeScript turns into):

if (user == null) {
return callback({
error: "User "+ username + " not found"

A potted summary

These are just some of the reasons that, despite ES6, CoffeeScript is my preferred way to write Javascript programs, both for NodeJS and for the browser. I’m a lazy programmer and CoffeeScript helps me write simpler, easier-to-understand code. I hope I’ve at least piqued enough interest for you to read the CoffeeScript manual (it’s only one page) and to give this language it a try yourself. Please let me know how you get on in the comments below.