---
title: 'CoffeeScript: Spartan JavaScript'
teaser:
tags: web,coffeescript,javascript,backbone.js
author: Nick Quaranto
published_on: 2011-08-22
---

I've been writing some CoffeeScript lately, and it's been fantastic. I wish I
had started looking into this language sooner. Here's some thoughts about it.

## the good

Writing CoffeeScript instead of JavaScript feels like I'm fighting a whole new
battle. JavaScript is not a verbose language. Writing JavaScript properly, and
in an OO manner, requires you to be verbose. What I like best is that
CoffeeScript is simply...spartan.

![''](http://i.imgur.com/2WfHe.jpg)

You bring only this snippet of code to battle?

![''](http://i.imgur.com/Twg6Y.jpg)

You! What is your keyword?

![''](http://i.imgur.com/5gZRh.jpg)

It's `function`, sir.

![''](http://i.imgur.com/YkRa4.jpg)

And you?

![''](http://i.imgur.com/aCyDM.jpg)

I'm `_.bindAll`, sir.

![''](http://i.imgur.com/1tCEp.jpg)

CoffeeScript! What are your keywords?

![''](http://i.imgur.com/PayPR.jpg)

    -> ! => ! -> !

![''](http://i.imgur.com/SXSbj.jpg)

See old friend, I brought better code than you did.

### functions & binding

I'm most excited about how accessible functions have become in CoffeeScript, and
how the worry of doing `_.bindAll` to keep the current object in `this` just
vanishes. Even our old friend `$(document).ready` loses a few pounds of syntax
weight:

    $ ->
      new ItemsRouter()
      Backbone.history.start()

It's ridiculously neat to me that it *just works*. If you're doing a loop or
something in a `Backbone.View` to render many things, you can use the "fat
arrow" to make sure `this` stays as the current object.

    class ItemView extends Backbone.View
      render: ->
        @options.items.each(@renderItem)
      renderItem: (item) =>
        @el.append item.get("title")

No more worrying about `_.bindAll`! Oh yeah, using `@` for instance methods (it
substitutes `this.`) is a great little cupcake of syntax sugar that makes code
so much easier to read.

### hashes/objects

We know the Ruby 1.8 syntax for hashes [is
dead](http://blog.pluralsight.com/rip-ruby-hash-rocket-syntax), but CS takes
this one step further. In this example, `Item` is a `Backbone.Model`:

    item = new Item title: "Awesome", id: 2

Omitting parentheses is something I've been trying with this transition. My
philosophy here is to push it to the limit and see how it feels. We'll see if it
passes [code
review](http://playbook.thoughtbot.com/working-in-feedback-loops/feature-branch-code-reviews/)
in the next few weeks.

### local variables

By default, JavaScript creates all variables in the global scope. How
[useful](https://twitter.com/#!/hgimenez/status/103574840019140608).

By default, CoffeeScript makes local variables by default and makes sure to
stick `var` in front of declarations.

    test = ->
      foo = "bar"
      console.log(foo)

    >> test()
    "bar"
    >> foo
    ReferenceError

This is reason enough to use CoffeeScript. I think anyone writing JavaScript has
to pay such close attention to scope that it's simply just a waste of time.

### string interpolation

How many times have you written something like:

    var html = "<option value='" + this.id + "'>" + this.get("title") + "</option>";

This is such nonsense. Why did we put up with this? In CoffeeScript, you can write:

    html = "<option value='#{@id}'>#{@get("title")}</option>"

By the way, the latest version of Backbone has a
[make](http://documentcloud.github.com/backbone/#View-make) method that helps
doing little element creation like this.

### inheritance

The [official docs](http://jashkenas.github.com/coffee-script/#classes) on the
subject put it best:

> JavaScript's prototypal inheritance has always been a bit of a brain-bender

So far I've used inheritance only in context with subclassing Backbone's core
classes, but I like what I'm seeing so far with the `class` and `extends`
keywords.

    class Item extends Backbone.Model
      url: ->
        "/events/#{@get('event_id')/items/#{@id}"

## The bad

### Debugging

This has been a major concern of mine since we've switched. Luckily it hasn't
been too bad yet, the JavaScript that is generated is actually readable. Of
course, there's the problem of there's not a one-to-one mapping between the JS
and CS, but we manage to get by with Sass/CSS just fine.

I have a feeling this will be an issue going forward, at least until Chrome or
[Firefox can understand CoffeeScript
natively](http://news.ycombinator.com/item?id=2503796).

### Silly keywords

"Silly" is probably the only way I can describe
[this](http://jashkenas.github.com/coffee-script/#operators):

    true, yes, on  true
    false, no, off  false

Not sure why we couldn't just stick with `true` and `false`. There are always
quirky parts to every language, but if I see `@item.has("title") == yes` in a
pull request I'll be sending a storm of commit comments.

### Deploying

I've been using [Barista](https://github.com/Sutto/barista) to integrate with
Rails 3.0 which has worked out quite well.

Our current `config/initializers/barista_config.rb` looks like:

    if Rails.env.development? || Rails.env.test?
      Barista.configure do |c|
        c.root = Rails.root.join("app", "assets")
        c.output_root = Rails.root.join("public", "coffeescripts")
        c.bare = true
        c.add_preamble = false
      end
    end

This tells Barista to look for coffeescripts in `app/assets`, which hopefully
will make the move to Rails 3.1 a little easier. We're dumping them into
`public/coffeescripts`, which is  is ignored by git so we don't check in the
generated files. Finally, there's some extra unnecessary noise that Barista adds
so the two final configuration options turns that off.

We're also using [Kumade](http://github.com/thoughtbot/kumade) to deploy to
Heroku's bamboo stack. I'm really hoping this entire situation gets easier in
the next few months, because right now it's a real annoyance to set up all of
this.

## the end

Hopefully this gives you a good overview of the nice additions that CoffeeScript
provides. We talked internally about using CoffeeScript for months before
integrating it. Part of me wishes we had done it sooner, but to really enjoy it
fully you have to understand the problems JavaScript has, especially in a large
codebase.

Huge thanks go out to the folks at DocumentCloud and Jeremy Ashkenas for making
JavaScript application development less painful. There's plenty of features I
didn't cover and pages of beautifully documented source code on the [project's
site](http://jashkenas.github.com/coffee-script/) that you should read.
