At Bookr we are moving our JavaScript to CoffeeScript mostly with the intent of making things more readable. I took some time out this weekend to familiarize myself with it by working through our code and doing some of the conversions. I’m not convinced that everything is more readable (example below) but it does make our Jasmine tests much easier to read.
The Good
Here’s the canonical example from the front of the Jasmine site.
describe("Jasmine", function() { it("makes testing JavaScript awesome!", function() { expect(yourCode).toBeLotsBetter(); }); });
Yeah, that looks like a BDD test (c.f. rspec) but functional JavaScript means lots of parentheses and curly braces. Ugh.
Oddly, CoffeeScript makes that look much better (apologies that WordPress doesn’t currently have a syntax highlighter for CoffeeScript):
describe "Jasmine", -> it "makes testing JavaScript awesome!", -> expect(yourCode).toBeLotsBetter()
I say “oddly” because the CoffeeScript site says it was designed to make it easier to write object-oriented code in JavaScript and while it has a nice class language that simplifies that for you it really excels at simplifying functional programming with JavaScript.
CoffeeScript really makes a difference when you have lots of it
clauses and sub-contexts:
describe "Jasmine", -> beforeEach -> fixture = ''' <div class="root"> <label for="email" /> <input type="email" id="email" value="me@example.com"/> </div> ''' it "makes testing JavaScript awesome!", -> expect(yourCode).toBeLotsBetter() describe "with existing JavaScript", -> it "includes all your other JS libs", -> expect($(fixture).find('#email').text()).toEqual 'me@example.com'
Also, as shown above, the heredoc really helped us clean up all the fixtures we use to test our Backbone views.
The Questionable
With Backbone.js, views have a $
method on them to allow finding DOM elements within their own tree. Something like this:
ExampleView = Backbone.View.extend({ render: function() { this.$('.email').text(this.email); } )}
In CoffeeScript every instance variable starts with @
. That’s basically converted directly to this.
when translated to JavaScript. It turns out that works for the $
function as well.
ExampleView = Backbone.View.extend render: -> @$('.email').text @email
Hmm…. is @$
really more readable? It’s starting to make me feel like I’m writing perl again.
Now I’m tempted to bundle in haml-js just so we can write out fixtures in haml.
You can now extend Backbone.View directly in Coffee, like so:
class MyView extends Backbone.View
initialize: ->
this.$
Also, you can still use ‘this’ if you prefer š