In Defense of Coffeescript
I often see arguments about whether or not using coffeescript is a good idea. Arguments against usually center around whether it’s a barrier for contributions, or whether it’s an unnecessary abstraction over another language that the developer needs to know anyhow.
I prefer writing Coffeescript to Javascript, and I use it whenever possible. In fact, my employer, Tapstream recently released a new frontend: an Ember.js application written entirely in coffeescript and mostly by me.
I believe that Coffeescript code is at least one of more succinct, more readable, and safer than equivalent Javascript code in just about any situation. Not only that, but Coffeescript helps you write correct Javascript code by default. Here are some of the ways that, in my opinion, Coffeescript helps you create better applications by avoiding common JS pitfalls.
Local scope by default.
If you don’t add a var
, Javascript assumes you meant to make a global variable. This
was sensible behavior in 1996 when you were writing mouseover scripts in the global scope,
but it’s hard to imagine that it would be considered a good idea if Javascript were created,
as a “real” programming language.
Of course, you can avoid this issue by always using var
, and in so doing gain more control over
your variables’ scope. But you’re not perfect, and you’ll sometimes forget a var
. And when you do,
javascript won’t be so kind as to warn you; things will work as expected, except for an unintentional
global that can cause subtle bugs later.
Existence operator
There’s often discussion about whether Java permitting the existence of
null
was a good idea or not. But Javascript has not one, but two null values, and just about
anything you do with that information that doesn’t involve treating them
identically is a path to madness.
In Javascript, to check if a value is either of null
or undefined
, you
can do this:
// Javascript
if(typeof myvar !== "undefined" && myvar !== null){
// Do a thing
}
You can, but you won’t, because you’re not that disciplined. More likely
you’ll fall back to if(myvar){}
and hope there are no valid falsy values
you forgot about (a more difficult question than it might be in a language with
a simpler truth table).
Coffeescript can protect you from yourself with a simple mechanism: a new operator,
?
, that checks for “existence” (i.e., not null
or undefined
). It looks like this:
# Coffeescript
if myvar?
# Do a thing
You can even chain it, if nullability doesn’t upset you:
# Coffeescript
maybeVal = myObject?.myNestedObject?.myVal
This is roughly equivalent to
// Javascript
maybeVal = ((myObject || {}).myNestedObject || {}).myVal || null
Sensible Looping and Comprehensions
One of the most annoying parts about working with Javascript is writing for loops like it’s 1989. It’s not difficult, it’s just not necessary. Just compare:
// Javascript
for(var ii=0; ii<myArray.length; ii++){
item = myArray[ii];
// Do something with item
}
and
# Coffeescript
for item in myArray
# Do something with item
There’s a lot less junk in the way, am I right? But what you may or may not have noticed is that the javascript contains a missing-var bug, which I chose not to correct after it emerged honestly while I was writing out that example.
Array comprehensions can help you take the readability and succinctness of your code one step further, for simple loops:
// Javascript
var myNewArray = [];
for(var ii=0; ii<myArray.length; ii++){
myNewArray.push(modify(myArray[ii]);)
}
// Do something with myNewArray
# Coffeescript
myNewArray = (modify(x) for x in myArray)
# Do something with myNewArray
Note that my javascript example leaves something out: the coffeescript pops the for loop
it compiles to inside a function, to keep the variable ii
out of the current scope. I
appreciate its consideration.
Default function arguments
Besides being shorter, there’s a safety aspect here, too; instead of this common pattern:
// Javascript
var myFunction = function(){
arg1 = arguments[0] || "default";
// Stuff
}
you can write:
# Coffeescript
myFunction = (arg1="default") ->
# Stuff
An be protected in case arg1 is a falsy-but-valid value.
Browser compatibility
Javascript has a separate implementation in every browser. Coffeescript’s implementation depends only on the subset of javascript available to all common browsers, right down to IE6. That means you don’t have to worry about whether any of the features mentioned above work in a given browser; you can safely assume it. You still have to ensure that you only use libraries and functions that work with your target browsers, of course.
Bonus feature: automatic last-statement returns
This is hit-or-miss, but I really like it, so I wanted to include it. Implicitly returning the last statement à la Ruby or Lisp is a nice little encouragement to write code in small, composable functions. It’s not a gamechanger, but I like it anyhow.
These aren’t the only advantages Coffeescript gives you, they’re just the ones that feel to me like they genuinely improve the situation, instead of being simple syntactic sugar.
Like videos better?
Webucator.com has made available a video inspired by this post: