Advertisement

Rocking Out With CoffeeScript

by

This Cyber Monday Tuts+ courses will be reduced to just $3 (usually $15). Don't miss out.

Even though CoffeeScript is a new language, you'll learn it very quickly. You should, since it's only JavaScript flaunting with some flashy clothes, after all. It reads like Ruby or Python, but compiles down to pure, non-fluffy JavaScript. Today, we're going to take a look at why everyone is talking about CoffeeScript.


A Word From the Author

With the advent of powerful JavaScript engines, like V8, JavaScript has shed its stigma of a gimped tool for juvenile interactions and morphed into quite a powerhouse. It has even jumped from client side applications to server side, node.js for instance. The fact that it adheres to a pretty nifty, prototype based ideology doesn't hurt it either. There is no doubt that JavaScript is indeed a critical language now and for the foreseeable future.

But I've always felt the syntax itself to be a bit kludgy. After working with a mix of Ruby and Python over the past couple of years, I've been finding JavaScript's semi-colon infused, parentheses dependent, verbose syntax to be tedious. And from what I can gather, I'm not alone in feeling this way. This is where CoffeeScript comes to the rescue!


What is CoffeeScript?

CoffeeScript compiles down to raw JS.

CoffeeScript is essentially just a syntactic rewrite of JavaScript. The core language itself stays the same, with small semantic enhancements. The syntax is modified, modeled after Python and Ruby.

Remember that the CoffeeScript compiler outputs clean JavaScript that not only follows best practices and is eminently readable but also passes JSLint. This means that you don't have to worry about compatibility down the line. In the worst case scenario of this project dying, you can just pick up the pristine JS that CoffeeScript generates and move on with your code. You aren't locked into this environment.

This may seem like an alien concept but under the web development umbrella, we've already seen our fair share of this ideology. HAML is but a new way of writing HTML while SASS does the same for CSS. All of them clean up the structure and syntax of their languages making them more easier to work with and thus boosting our productivity.


Some Quick Code

You're probably wondering how the code itself looks so here is a quick peek:

index = (list, target) ->
  [low, high] = [0, list.length]
  while low < high
    mid = (low + high) >> 1
    val = list[mid]
    return mid if val is target
    if val < target then low = mid + 1 else high = mid
  return -1

This is a quick implementation of a binary search. Don't try to parse the code itself right now. Just try to familiarize yourselves with the syntax.

Below is the JavaScript code that CoffeeScript generates:

var index;
index = function(list, target) {
  var high, low, mid, val, _ref;
  _ref = [0, list.length], low = _ref[0], high = _ref[1];
  while (low < high) {
    mid = (low + high) >> 1;
    val = list[mid];
    if (val === target) {
      return mid;
    }
    if (val < target) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }
  return -1;
};

Pros and Cons

Here are some quick advantages and disadvantages of using CoffeeScript. This isn't comprehensive by any means but I think this is sufficient to get a quick overview of the system.

Yays

  • Python style whitespacing
  • Ruby styled lightweight syntax
  • Concise function declarations
  • JSLint approved
  • Class based inheritance

There are, of course, numerous other points including semantic and syntactic enhancements.

Nays

  • Slight learning curve involved
  • Deployment, depending on your route, may be a chore
  • You'll need a basic knowledge of JS for debugging purposes. You can't directly start here, naturally.

Getting Started

The official methods to get started include a command line utility that runs under node.js and simply downloading the source and installing it. Nothing much to guide here. Get the node.js utility and use npm install coffee-script [or for the source, bin/cake install] to install and get started.

The situation with Windows is slightly more complicated. There is no straight forward way to get node.js or the source installed on Windows [outside of Cygwin]. Never fret though. A number of enterprising people have written compilers that work natively on Windows. I've included a few below:

Note that the compiler, in compiled JavaScript form, is also bundled with the source, if you're interested. It's present under the extra directory with an obvious name.

With that out of the way, we're now going to take a look at a handful of things that show you how CoffeeScript makes JavaScript easier to consume!


Use of Whitespace

The first thing you'll need to know is how CoffeeScript uses whitespace effectively to simplify the syntax. People with a Python background will find this trivial but for the others, here is a quick explanation.

First up, you need not end every line with a semi-colon. Ending a line is automatically interpreted to be the end of that statement. For example, this..

numbers = [0, 1, 2, 3]
name = "NetTuts+"

.. compiles down to this:

var name, numbers;
numbers = [0, 1, 2, 3];
name = "NetTuts+";

Next, you'll be happy to know that you can do away with curly braces. Those numerous braces for opening and closing a block? Everything's out. In CoffeeScript, you use Python-esque indentation to signify the beginning and ending of a block.

CoffeeScript doesn't require unnecessary parentheses or curly braces.

Here is a quick example. Disregard everything but the indentation for now. We'll get to the rest a little later below:

if chasedByCylons
 runForYourLife()

.. compiles down to

if (chasedByCylons) {
  runForYourLife();
}

If you're still a little confused, don't worry. The syntax will start making more sense once we get to know the language better.


Nifty, Semantic Aliases

CoffeeScript provides a number of aliases for operators and keywords to make the code more readable and intuitive. Let's take a look at some of them now.

First, the comparison operators:

  • is maps to ===
  • isnt compiles to !==
  • == and != compile to === and !== respectively [As a best practice]

Let's see them in action quickly.

if pant is onFire
 lookForWater()

if game isnt good
 badMouth();

..which compiles to..

if (pant === onFire) {
  lookForWater();
}
if (game !== good) {
  badMouth();
}

Pretty easy to read, no? Now, on to how logical operators are mapped.

  • and maps to &&
  • or is an alias for ||
  • not compiles down to !

Building on our previous code:

if pant is onFire and not aDream
 lookForWater()

if game isnt good or haughtyDevs
 badMouth();

..which compiles to..

if (pant === onFire && !aDream) {
  lookForWater();
}
if (game !== good || haughtyDevs) {
  badMouth();
}

Conditionals

As you've already seen above, the basic if/else construct behaves the same as in normal JavaScript, sans the parentheses and curly braces. We'll look at some variations below.

if tired and bored
 sleep()
else 
 jog()
 
// Raw JS below

if (tired && bored) {
  sleep();
} else {
  jog();
}

And here's how the ternary operator is handled:

activity = if sunday then isChilling else isWorking
 
// Raw JS below

activity = sunday ? isChilling : isWorking;

An additional semantic enhancement is with the unless keyword. This functions as the exact opposite of if.

keepRunning() unless tired

keepWorking unless focus is extremelyLow

And the compiled JavaScript...

if (!tired) {
  keepRunning();
}
if (focus !== extremelyLow) {
  keepWorking;
}

Switch-Case

Switch statements can be a little obtuse in JavaScript. CoffeeScript provides an intuitive wrapper around this construct.

It begins with the switch keyword, as expected, followed by the variable whose value we're checking. Each case or possible value is preceded by the when keyword followed by the statements to execute if it's a match.

There's no need to add a break statement at the end of every case statement: CoffeeScript does this automatically for you.

switch time
 when 6.00 
  wakeUp()
  jotDownList()
 when 9.00 then startWorking()
 when 13.00 then eat()
 when 23.00
  finishUpWork()
  sleep()
 else doNothing()

The syntax should be fairly self explanatory if you already know the equivalent in JavaScript. The only point to note here is the use of the then keyword. It's used to separate the condition from the expression without starting a new line. You can use then for the other conditional statements as well as loops too.

Here's the JS that CoffeeScript generates for you:

switch (time) {
  case 6.00:
    wakeUp();
    jotDownList();
    break;
  case 9.00:
    startWorking();
    break;
  case 13.00:
    eat();
    break;
  case 23.00:
    finishUpWork();
    sleep();
    break;
  default:
    doNothing();
}

Basic Loops

Looping is another essential construct for your typical JavaScript code. Be it looping through numbers in an array or nodes in the DOM, you're always in need of looping through collections.

CoffeeScript provides a very flexible while loop that can be modified to function as a generic for or do-while loop.

while work > time then freakOut()

while time > work 
  relax()
  mozyAround()

// Raw JS

while (work > time) {
  freakOut();
}
while (time > work) {
  relax();
  mozyAround();
}

until is another semantic enhancement and is equivalent to while not. A quick example below:

workOut() until energy < exhaustion 

// Raw JS

while (!(energy < exhaustion)) {
  workOut();
}

Looping Through Collections

Looping over arrays is pretty easy. You'll need to use the for..in construct to step through the array. Let me show you how:

sites = ['CodeCanyon','ThemeForest','ActiveDen']
for site in sites
 alert site

If you prefer the statements to be in the same line:

sites = ['CodeCanyon','ThemeForest','ActiveDen']
alert site for site in sites

CoffeeScripts compiles these to basic for loops like so. Note that in line with best practices, the length of the array is cached beforehand.

var site, sites, _i, _len;
sites = ['CodeCanyon', 'ThemeForest', 'ActiveDen'];
for (_i = 0, _len = sites.length; _i < _len; _i++) {
  site = sites[_i];
  alert(site);
}

Iterating over associate arrays [or hashes or dictionaries or key-value pairs] is just as easy with the of keyword.

managers = 'CodeCanyon': 'Jeffrey Way', 'ThemeForest': 'Mark Brodhuber', 'ActiveDen': 'Lance Snider'

for site, manager of managers
  alert manager + " manages " + site

As expected, the above compiles down to a basic for loop as shown below:

var manager, managers, site;
managers = {
  'CodeCanyon': 'Jeffrey Way',
  'ThemeForest': 'Mark Brodhuber',
  'ActiveDen': 'Lance Snider'
};
for (site in managers) {
  manager = managers[site];
  alert(manager + " manages " + site);
}

Functions

Creating and using functions is extremely easy under CoffeeScript. To define a function, you list the parameters it takes and then go on with the function's body. Here, let me show you how:

playing = (console, game = "Mass Effect") ->
  alert "Playing #{game} on my #{console}."

playing 'Xbox 360', 'New Vegas'

This is the basic syntax behind creating and using functions. The default value for parameters can be defined inline. CoffeeScript generates the code to check whether a value has been passed in or not.

Invoking a function is just as easy. There's no need for parentheses: pass in the parameters one after the other.

As always, here's the generated code for your reference:

var playing;
playing = function(console, game) {
  if (game == null) {
    game = "Mass Effect";
  }
  return alert("Playing " + game + " on my " + console + ".");
};
playing('Xbox 360', 'New Vegas');

Embedding Raw JavaScript

Sometimes, you may have no other choice but to use raw JavaScript inside your CoffeeScript code. Hopefully, these instances should be far and few between but this has been taken into account as well.

You can inject raw JS into your code by wrapping it with grave accents, also known as a backquote or backtick. Anything passed in thus will be completely untouched by the CoffeeScript compiler.

rawJS = `function() {
  return someSuperComplexThingie;
}`

// which nets you

var rawJS;
rawJS = function() {
  return someSuperComplexThingie;
};

What Happens to My Libraries?

Nothing happens to them, they can stay exactly where they are. CoffeeScript works seamlessly with any third party library, big or small, because it simply compiles to raw JavaScript. You'll just have to reformat and/or refactor your code very slightly but other than that, incompatibilities shouldn't be a point of concern.

So instead of writing this:

$(document).ready(function() {
 elemCollection = $('.collection');
  for (i=0; i<=elemCollection.length;i++)
  {
    item = elemCollection[i];
   // check for some random property here. I am skipping the check here  
   colortoAdd = item.hasProperty()? yesColor : noColor;
   // I'm quite aware there are better ways to do this 
   $(item).css ('background-color', colortoAdd);
  }
});

... you'd write..

$(document).ready ->
    elemCollection = $('.collection')
    for item in elemCollection    
      colortoAdd = if item.hasProperty() then yesColor else noColor
      $(item).css 'background-color', colortoAdd

That's All Folks

And we've come to an end. I haven't covered a number of higher levels topics, classes for example, because they're well beyond the scope of an introductory article. Look for some advanced CoffeeScript tutorials down the road!

I think CoffeeScript has changed the way I write JavaScript and, after reading this, I hope it has changed yours too. Questions? Nice things to say? Criticisms? Hit the comments section and leave me a comment. Happy coding and thank you so much for reading!

Advertisement