---
title: Replace CoffeeScript with ES6
teaser: Use ES6 on your next project.
tags: web,javascript,es6,coffeescript
author: Blake Williams
published_on: 2015-01-30
---

I've been looking into [ES6], the next version of JavaScript, and finally got a
chance to use it on a project. In the brief amount of time I was able to use it
I've found that it solves a lot of the problems that [CoffeeScript] is trying to
solve without drastic syntax changes.

[ES6]: http://en.wikipedia.org/wiki/ECMAScript#ECMAScript_Harmony_.286th_Edition.29
[CoffeeScript]: http://coffeescript.org/

## Using ES6 Today

We can start using ES6 today through the 6to5 project which transpiles our ES6
code into ES5. 6to5 supports a plethora of build tools including Broccoli,
Grunt, Gulp, and Sprockets. I've had a lot of success using [sprockets-es6], and
Sprockets 4.x will have out-of-the-box support for 6to5.

If you're using Vim you'll want to associate the `.es6` file extension with
JavaScript by putting the following code into your `.vimrc`.

```vim
autocmd BufRead,BufNewFile *.es6 setfiletype javascript
```

You can also use the 6to5 REPL to try out ES6 in your browser.

[sprockets-es6]: https://github.com/TannerRogalsky/sprockets-es6

## Classes

Both CoffeeScript and ES6 have class support.  Let's look at a CoffeeScript class
compared to the ES6 equivalent.

CoffeeScript allows us to take advantage of setting instance variables from the
parameters, string interpolation, and calling functions without parentheses:

```coffeescript
class Person
  constructor: (@firstName, @lastName) ->

  name: ->
    "#{@first_name} #{@last_name}"

  setName: (name) ->
    names = name.split " "

    @firstName = names[0]
    @lastName = names[1]

blake = new Person "Blake", "Williams"
blake.setName("Blake Anderson")
console.log blake.name()
```

With ES6 we can take advantage of classes, getters, and setters:

```javascript
class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  get name() {
    return this.firstName + " " + this.lastName;
  }

  set name(name) {
    var names = name.split(" ");

    this.firstName = names[0];
    this.lastName = names[1];
  }
}

var blake = new Person("Blake", "Williams");
blake.name = "Blake Anderson"
console.log(blake.name);
```

If you've used any library or framework that provides classes in JavaScript
you'll notice the ES6 syntax has some minor differences:

* There is no semicolon after the function name
* The `function` keyword is omitted
* There are no commas after each definition

We're also taking advantage of getters and setters which allow us to treat the
`name` function like a property.

## Interpolation

I've often wished for a more powerful string syntax in JavaScript. Fortunately
ES6 introduces [template strings]. Let's compare CoffeeScript strings,
JavaScript strings, and template strings to see what each is capable of.

CoffeeScript:

```coffeescript
"CoffeeScript allows multi-line strings
with
interpolation like 1 + 1 = #{1 + 1}
"
```

JavaScript strings:

```javascript
"JavaScript strings can only span a single line " +
  "and interpolation isn't possible"
```

ES6 template strings:

```javascript
`Template strings allow strings to span
multiple lines and allow interpolation like 1 + 1 = ${1 + 1}
`
```

We can take advantage of template strings in our previous example by changing
our `name` getter to the following:

```javascript
get name() {
  return `${this.firstName} ${this.lastName}`;
}
```

This feels much cleaner than the string concatenation we were doing before and
gets us closer to the CoffeeScript example.

[template strings]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings

## Fat Arrows

Another feature that made CoffeeScript so appealing also makes an appearance
in ES6: fat arrows. Fat arrows allow us to bind a function to the current value
of `this`. First, let's take a look at how we can handle this without a fat
arrow.

With ES5 we have to keep a reference to the current value of `this` when
defining the function:

```javascript
var self = this;

$("button").on("click", function() {
  // do something with self
});
```

CoffeeScript fat arrows can omit arguments and parentheses entirely:

```coffeescript
$("button").on "click", =>
  # do something with this
```

ES6 fat arrows require the parentheses with or without arguments:

```javascript
$("button").on("click", () => {
  // do something with this
});
```

## Other features

ES6 has a few other features worth worth noting in passing.

### Default arguments

CoffeeScript:

```coffeescript
hello = (name = "guest") ->
  alert(name)
```

ES6:

```javascript
var hello = function(name = "guest") {
  alert(name);
}
```

### Splats

[Variadic functions], which CoffeeScript calls splats, allow you to
collect additional arguments passed to your function as an array. ES6 refers to
them as rest arguments.

[Variadic functions]: http://en.wikipedia.org/wiki/Variadic_function

CoffeeScript:

```coffeescript
awards = (first, second, others...) ->
  gold = first
  silver = second
  honorable_mention = others
```

ES6:

```javascript
var awards = function(first, second, ...others) {
  var gold = first;
  var silver = second;
  var honorableMention = others;
}
```

### Destructuring

Destructuring allows you to pattern match against arrays and objects to extract
specific values.

CoffeeScript:

```coffeescript
[first, _, last] = [1, 2, 3]
```

ES6:

```javascript
var [first, , last] = [1, 2, 3]
```

We can use destructuring in the `name` setter we defined earlier to make our
code more concise:

```javascript
set name(name) {
  [this.firstName, this.lastName] = name.split(" ");
}
```

## Wrapping Up

ES6 transpilers are actively being developed and are catching up to CoffeeScript
in functionality. This post only covered a handful of the features that ES6 is
bringing to JavaScript.

On your next project set CoffeeScript aside and give ES6 a shot!
