Over a million developers have joined DZone.

Why I'm Finally Switching to CoffeeScript

· Web Dev Zone

Make the transition to Node.js if you are a Java, PHP, Rails or .NET developer with these resources to help jumpstart your Node.js knowledge plus pick up some development tips.  Brought to you in partnership with IBM.

CoffeeScript Misconceptions

 
You may have already heard about CoffeeScript and some of the hype surrounding it but you still have found several reasons to not make the switch. This blog post is for you. Here are some of the reasons I held out for so long:
  • I wanted to understand Javascript and just didn't see how using a "simpler version" (my own thoughts) would make my life easier in the long run.
  • If I DID use an intermediate language, I wanted to be able to dump it at any time and not feel like I was forced to continue using it.
  • Putting one more thing with bugs in between myself and my code seemed fool hardy.
So here's the reasons I finally switched:
  • It's less verbose Javascript, not a different or simplified language.
  • A couple of shortcuts that enable you to use list comprehensions rather than error prone for statements.
  • CoffeeScript compiles to pretty awesome Javascript. I wouldn't have any concern dumping CoffeeScript at any time because of this. It would also have put some great conventions in my Javascript that I could follow.
  • Eli Thompson is always right. (You should read his blog. He's smart: http://eli.eliandlyndi.com/)

 For-Loop Boiler Plate Banished

Here's an example of several Javascript for-loops embedded in a switch statement:
    document.onkeydown = function(event) {
      var game_piece, _i, _j, _k, _l, _len, _len2, _len3, _len4, _len5, _len6, _m, _n;
      switch (event.keyCode) {
        case 37:
          for (_i = 0, _len = game_pieces.length; _i < _len; _i++) {
            game_piece = game_pieces[_i];
            game_piece.pan_left();
          }
          break;
        case 38:
          for (_j = 0, _len2 = game_pieces.length; _j < _len2; _j++) {
            game_piece = game_pieces[_j];
            game_piece.pan_up();
          }
          break;
        case 39:
          for (_k = 0, _len3 = game_pieces.length; _k < _len3; _k++) {
            game_piece = game_pieces[_k];
            game_piece.pan_right();
          }
          break;
        case 40:
          for (_l = 0, _len4 = game_pieces.length; _l < _len4; _l++) {
            game_piece = game_pieces[_l];
            game_piece.pan_down();
          }
          break;
        case 189:
          for (_m = 0, _len5 = game_pieces.length; _m < _len5; _m++) {
            game_piece = game_pieces[_m];
            game_piece.zoom_out();
          }
          break;
        case 187:
          for (_n = 0, _len6 = game_pieces.length; _n < _len6; _n++) {
            game_piece = game_pieces[_n];
            game_piece.zoom_in();
          }
      }
      return the_screen.refresh(game_pieces);
    };

GNARLY! Now obviously we could clean this code up a bit... but seriously... 

 

Well let's just see that same code in CoffeeScript and how much better it can be:
  document.onkeydown = (event)->
    switch event.keyCode
      when 37 then game_piece.pan_left() for game_piece in game_pieces
      when 38 then game_piece.pan_up() for game_piece in game_pieces
      when 39 then game_piece.pan_right() for game_piece in game_pieces
      when 40 then game_piece.pan_down() for game_piece in game_pieces
      when 189 then game_piece.zoom_out() for game_piece in game_pieces
      when 187 then game_piece.zoom_in() for game_piece in game_pieces
    the_screen.refresh(game_pieces)
That's the power of expressions.

Less Complex OO

Now how about classes? These are the bane of Javascript programmers everywhere. There are few right ways to do them and a billion wrong ways. CoffeeScript classes are the biggest simplification CoffeeScript makes to Javascript and was a big reason for my holding out for so long. Really though, they're just short hand that removes a bunch of boiler plate so I have less opportunity to introduce bugs. Here's a simple example:
 
Simple Javascript class:
  var foo = (function() {
    function foo(param1, param2) {
      alert("I've been constructed!");
    }
    foo.prototype.bar = function() {
      return it.shake_like(a_polaroid_picture);
    };
    return foo;
  })();
Same class in CoffeeScript:
class foo
  constructor: (param1, param2)->
    alert "I've been constructed!"
  bar: ->
    it.shake_like(a_polaroid_picture)

Get Off My Lawn

In the past, people tried compiling to Javascript simply because they didn't get it. This is different. It's been over a decade since Javascript began to see wide use and enough of us get it now that we're starting to see tools that don't try to cover it up for being a broken language. Instead, we're seeing improvements made to a programming language we love and think can be even better. The only reason I see remaining to stick with Plain Old Javascript is nostalgia and fear of change.
I'll leave you with one last example. It's a full set of CoffeeScript that does drag/drop and zoom/pan in canvas. You can decide for yourself which version of the code you'd rather work on.
Before CoffeeScript:
  hand = (function() {
    function hand() {
      this.held_item = null;
    }
    hand.prototype.interact_at = function(x, y) {
      if (this.held_item !== null) {
        return this.drop_tile_if_over_it(x, y);
      } else {
        return this.pick_up_tile_if_over_it(x, y);
      }
    };
    hand.prototype.move_to = function(x, y) {
      if (this.held_item !== null) {
        return this.held_item.drag_to(x, y);
      }
    };
    hand.prototype.can_interact_with = function(touchable_game_pieces) {
      return this.game_pieces = touchable_game_pieces;
    };
    hand.prototype.drop_tile_if_over_it = function(x, y) {
      var game_piece, _i, _len, _ref, _results;
      _ref = this.game_pieces;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        game_piece = _ref[_i];
        if (game_piece.is_at(x, y)) {
          this.held_item = null;
          break;
        }
      }
      return _results;
    };
    hand.prototype.pick_up_tile_if_over_it = function(x, y) {
      var game_piece, _i, _len, _ref, _results;
      _ref = this.game_pieces;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        game_piece = _ref[_i];
        if (game_piece.is_at(x, y)) {
          this.held_item = game_piece;
          this.held_item.start_dragging(x, y);
          break;
        }
      }
      return _results;
    };
    return hand;
  })();
After CoffeeScript:
class hand
  constructor: ->
    @held_item = null
  interact_at: (x,y)->
    if @held_item != null
      @drop_tile_if_over_it(x, y)
    else
      @pick_up_tile_if_over_it(x, y)
  move_to: (x,y)->
    if @held_item != null
      @held_item.drag_to(x, y)
  can_interact_with: (touchable_game_pieces)->
    @game_pieces = touchable_game_pieces
  drop_tile_if_over_it: (x,y)->
    for game_piece in @game_pieces
      if game_piece.is_at x, y
        @held_item = null
        break;
  pick_up_tile_if_over_it: (x,y)->
    for game_piece in @game_pieces
      if game_piece.is_at x, y
        @held_item = game_piece
        @held_item.start_dragging x, y
        break;

 

 

 

Learn why developers are gravitating towards Node and its ability to retain and leverage the skills of JavaScript developers and the ability to deliver projects faster than other languages can.  Brought to you in partnership with IBM.

Topics:

Published at DZone with permission of Justin Bozonier, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}