Some lesser-known Coffeescript features you might not know about

Directly assign properties on this from function

Often in function declarations – particularly constructor functions – we want to assign properties on this from the function signature:

class Dog
  constructor: (name, age) ->
    @name = name
    @age  = age

We can clear this up a little with CoffeeScript’s destructuring syntax (note the array brackets – which are required, unlike Ruby):

class Dog
  constructor: (name, age) ->
    [@name, @age] = name, age

However, CoffeeScript allows the implicit assignment of properties on this from the function signature, so we can just do this:

class Dog
  constructor: (@name, @age) ->

No function body needed! Quite often this is all you’re doing in a constructor, so I find it’s not unusual for this to be the norm rather than the exception.

For the curious, this is what the example above is compiled into (omitting the outer IIFE) – pretty much the same as the first example:

var Dog;

Dog = (function() {
  function Dog(name, age) {
    this.name = name;
    this.age = age;
  }

  return Dog;

})();

Shorthand for object assignment

How often have you written something like the following?

createDog = (name, age) ->
  options = { name: name, age: age }

  API.post "/dogs", options

If you’re naming your variable names sensibly, it’s pretty common to have the same name for a variable and the object property you’re assigning it to. Fortunately, CoffeeScript has a handy shorthand for just this case:

createDog = (name, age) ->
  options = { name, age }

  API.post "/dogs", options

This also works with properties on this :

class Dog
  create: ->
    options = { @name, @age }

    API.post "/dogs", options

Quick and easy closures

Invoking an asynchronous function for every item in a collection often introduces a subtle bug:

for url in pages
  $.get url, (results) ->
    doSomethingWith(url, results) # <- url will have changed at this point

Since JavaScript doesn’t have lexical closures (until ES6 is commonly available and we can use let instead), the value of url will have changed by the time the callback fires, since for loops don’t introduce a new scope.

Luckily, CoffeeScript has our back in cases like this – the do keyword:

for url in pages
  do (url) ->
    $.get url, (results) ->
      doSomethingWith(url, results)

This defines an anomymous function to close over our requested variable (url in this case), then invokes it.

Generally, this problem disappears if you break down your code into small, well-named functions, but it’s a useful feature nonetheless.

Summary

Any other CoffeeScript features I’ve missed? Let us know in the comments.

Photo by peter barwick on Flickr