10 CoffeeScript Features You Might Not Know

This week I’ve spent some time researching different CoffeeScript resources to be used for training at a client. In the process I’ve discover a few CoffeeScript features that I didn’t know about or are not that well known.

Iterations

You probably know the standard way of iterating through a list in CoffeeScript.

for name in ['Tom','Dick','Harry']
  alert "Hi, #{name}"

But did you know that by passing an extra argument, you can also get the current iteration index?

for name, i in ['Tom','Dick','Harry']
  alert "Hi, #{name} - you are number #{i}"

Splatting

JavaScript (and therefore CoffeeScript) doesn’t enforce that you pass the correct number of parameters to a function. In this example the last few parameters will just get dropped.

planets = (first, second, third) ->
  alert third
  
planets 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter'
# alert will be 'Earth'

But did you know that CoffeeScript supports splatting?

planets = (first, second, others...) ->
  alert others

planets 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter'
# alert will be 'Earth','Mars','Jupiter'

Comprehensions

CoffeeScript also supports comprehensions – a little bit like the map function in Ruby.

class Person
  constructor: (name, email) ->
    @name = name
    @email = email

userEmails =
  tom: 'tom@example.com'
  dick: 'dick@example.com'
  harry: 'harry@example.com'

contacts = for name, email of userEmails
  new Person(name,email)

Destructuring Assignment

Destructuring Assignment is just a fancy way of saying we can assign multiple variables at once. You can use it to switch the value of two variables in a single line.

one = 1
two = 2
[one, two] = [two, one]

You can also use this to assign variables to the result of a function.

date = ->
  [25,'April',2013]

[day, month, year] = date()

It even works with deeply nested objects!

person =
  name: 'John'
  email: 'john@example.com'
  address:
    street: [
      '123 Main Street'
      'Apt 8B'
    ]
    city: 'Gotham'
    zip: '8442'

{ address: { street: [_, apartment], city } } = person

Destructuring Assignment combined with Splatting

Destructuring Assignment also works when combined with Splatting, which gives you another powerful way of dealing with arrays of variable length.

daysOfTheWeek = "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday"

[first, rest..., last] = daysOfTheWeek.split ','

Chained Comparisons

CoffeeScript also allows us to do Chained Comparisons (borrowed from Python) – which allows us to easily test if a value fall within a certain range.

temperature = 72
niceDay = 82 > temperature > 68

Block Strings

You probably know that CoffeeScript supports string interpolation (using the same syntax as Ruby).

name = "John"
surname = "Doe"

greeting = "Hi, #{name} #{surname}"

But did you know that JavaScript supports block strings? This is very useful for formatted or indentation-sensitive text. The indentation level that begins the block is maintained throughout, so you can keep it all aligned with the body of your code.

html = """
       <p>
       Hi, #{name} #{surname}
       </p>
       """

Prototype Shorthand

You probably know that @ is the shorthand for accessing this in CoffeeScript. But did you know that CoffeeScript has a similar shorthand for accessing the prototype of a class?

String::pipeDelimited = ->
  @split '|'

alert "ABC|abc".pipeDelimited()

Binding Parameters to Properties

CoffeeScript allows us to bind parameters to properties directly by using the @ shorthand. For example, you often want to set properties in the constructor.

class Person
  constructor: (name) ->
    @name = name

But we can just bind this property in the function declaration. CoffeeScript is the only language that I know of that allows you to do this.

class Person
  constructor: (@name) ->

Class/Static Functions

The @ shorthand also allows us to define class functions.

class Number
  @random: ->
    return 4  # chosen by fair dice roll
              # guaranteed to be random
              
alert Number.random()

My random implementation is a reference to XKCD.

Happy coding.