49

Of course one big pro is the amount of syntactic sugar leading to shorter code in a lot of cases. On http://jashkenas.github.com/coffee-script/ there are impressive examples. On the other hand I have doubts that these examples represent code of complex real world applications. In my code for instance I never add functions to bare objects but rather to their prototypes. Moreover the prototype feature is hidden from the user, suggesting classical OOP rather than idiomatic Javascript.

The array comprehension example would look in my code probably like this:

cubes = $.map(list, math.cube); // which is 8 characters less using jQuery...
6
  • 7
    That's not array comprehension. That's JQuery.map(). Apr 29, 2011 at 21:27
  • 1
    Sure, therefore I'm not referring to "array comprehension" itself but to the "array comprehension example [on the website]".
    – Philip
    Apr 29, 2011 at 21:40
  • Fair enough. My point was jut that foldl (map) is in some ways a degenerate case of list comprehension (which is typically more powerful). Apr 29, 2011 at 21:43
  • Well basically I'm asking this question because I wonder whether it is a stupid decision to use Javascript rather than Coffeescript. I agree, array comprehension is much more powerful on the other hand nobody would argue that Python is more powerful than Ruby because of array comprehension and marking blocks by indentation rather than begin/end.
    – Philip
    Apr 29, 2011 at 21:50
  • Rails made coffee script a default gem. It provoked "discussion" github.com/rails/rails/commit/… Apr 29, 2011 at 22:51

6 Answers 6

54

I'm the author of a forthcoming book on CoffeeScript:
http://pragprog.com/titles/tbcoffee/coffeescript

I was convinced that CoffeeScript was worth using after about a week of playing with it, even though the language was only a few months old at the time and had many more rough edges than it does now. The official site does a great job of listing (most of) the language's features, so I won't repeat those here. Rather, I'll just say that the pros of the language are:

  1. Encourages the use of good JavaScript patterns
  2. Discourages JavaScript anti-patterns
  3. Makes even good JavaScript code shorter and more readable

No. 3 gets a lot more attention than the first two (even in my book), but the more I think about it, the more I realize that I didn't make the jump just for the pretty syntax; I made the jump because the language nudged me toward better, less error-prone JavaScript. To give a few quick examples:

  • Because variables are auto-scoped, you can't accidentally overwrite globals by omitting var, shadow a variable with the same name (except with named arguments), or have variables in different files that interact (see https://stackoverflow.com/questions/5211638/pattern-for-coffeescript-modules/5212449).
  • Because -> is a heck of a lot easier to write than function(){}, it's easier to use callbacks. Semantic indentation makes it clear when callbacks are nested. And => makes it easier to preserve this when appropriate.
  • Because unless x is easier for English speakers to parse than if (!x), and if x? is easier than if (x != null), to give just two examples, you can spend fewer brain cycles on logic syntax and more on the logic itself.

A great library like Underscore.js can take care of some of these problems, but not all.

Now for the cons:

  1. Compilation can be a pain. The syntax errors the CoffeeScript compiler throws are often vague. I expect progress to be made on that track in the future. (In the compiler's defense, it often catches things that—if you wrote them in JavaScript—you wouldn't discover as an error until that line of code ran. Better to catch those bugs sooner than later.)
  2. Relatedly, debugging can be a pain. There isn't yet any way to match compiled JS lines to the original CoffeeScript (though the Firefox folks have promised that this is coming).
  3. It's prone to change. Your code may run differently, or not run at all, under a future version of CoffeeScript. Of course, this is the case with most languages—moving to a new version of Ruby or Python is similar—but it's not the case with JavaScript, where you can reasonably expect that code that runs fine across major browsers today will run fine across major browsers for as long as the web as we know it exists.
  4. It's not as well-known. JavaScript is a lingua franca. CoffeeScript has become very popular in a short amount of time, but it's unlikely that it'll ever enjoy as vast a community as JavaScript.

Obviously I think the pros outweigh the cons for me personally, but that won't be the case for every person, team, or project. (Even Jeremy Ashkenas writes a lot of JavaScript.) CoffeeScript is best viewed as a fine complement to JavaScript, not a replacement.

8
  • 2
    Whoa whoa whoa, how in the world did I miss => in the documentation? That's awesome. (The other points were good too--very good unbiased answer with an honest list of cons. :) Apr 30, 2011 at 5:30
  • Thank you for your detailled answer. Though I'll wait a bit to accept it, it would be interesting to have pros/cons considering the different OOP approaches.
    – Philip
    May 3, 2011 at 16:52
  • 2
    I'd say that CoffeeScript's class model is more accessible to newcomers than JavaScript's prototype model and supports good practices (in particular, defining your prototypes in one place rather than scattering Foo.prototype.bar = ... lines all over, which is madness!). It's a great way to cleanly organize code. On the other hand, it may cause people to use OOP even when a functional approach is much more elegant. May 4, 2011 at 17:32
  • Some of indentation logic doesnt quite behave as expected, you have to look at the underlying JS to see thats its done something thats totally weird.. It might be part of the ruleset tbh, but it isnt always obvious vs other indent senstitive languages such as Py, and I've found this can generate more subtle bugs than the ones it is meant to prevent. I still use CoffeeScript though
    – sa93
    Aug 15, 2011 at 8:04
  • 1
    Points 1 and 2 need detail. I think Andrew's answer provides a good example of #3 as a mixed bag. I disagree with the bullets: forgetting var is silly and you shouldn't have a lot of global vars to collide with in the first place, 'function' is not hard - pre-defined named methods even less so, 'if(!x)' is short and sweet and 'unless' makes it more verbose (see your own previous bullet and point #3) and human language-resemblance is actually not a design goal that has historically met with a lot of success in programming languages. We need to be in touch with human and machine. Jun 22, 2013 at 3:05
33

We have a somewhat large JavaScript codebase and about a month ago we desided to give CoffeeScript a try. One of our developers started with migrating one of our modules from JS to CS using http://js2coffee.org/. This tool was rather handy and it took about two or three hours to port a 1000-something lines of JavaScript. Some observations we've noticed at that point:

  1. The resulting CoffeeScript code was quite readable.

  2. We compiled it back to JavaScript and it was pretty easy to navigate and to debug. While we were porting that module another developer from our team found a bug in it. These two developers fixed that bug in our old JavaScript code and in new JavaScript code that came out of CS compiler. They worked independently and it took them about the same amount of time (15-20 minutes).

  3. Because of the fact that it was a port the resulting code were not using Coffee-specific features that were appropriate or desirable. If we would write in CoffeeScript from scratch the code would be more idiomatic. Because of that later we decided that we won't port the existing code.

  4. In general readability of shorter function and smaller object increased to some extend. However, for longer methods that wasn't the case at all. The biggest bloat savings came from -> and explicit return, but other than that our code hadn't got significantly shorter or simpler. Some pieces of syntax seemed quite confusing, especially object literals. CS omits curly braces around member definitions and combined with "everything-is-an-expression" and implicit return that made some bits of code pretty hard to read.

    Here's JavaScript:

    var rabbitGenerator = {
        makeRabbit: function(rabbitName, growCarrots) {
            if (growCarrots) {
                carrots.growMore(10);
            } else {
                carrots.ensureSupply();
            }
            return {
                name: rabbitName, 
                height: 0,
                actions: {
                    jump: function (height) {
                        this.height += height;
                    },
                    eatCarrot: function () {
                        // etc
                    }
                }
            };
        },
        // more members
    }
    

    And here's what the corresponding CoffeeScript code would look like:

    rabbitGenerator = 
      makeRabbit: (rabbitName, growCarrots) ->
        if growCarrots
          carrots.growMore 10
        else
          carrots.ensureSupply()
        name: rabbitName // (*)
        height: 0
        actions: 
          jump: (height) ->
            @height += height
    
          eatCarrot: ->
    

    As it is now it's pretty difficult to figure out that the return statement starts at (*) line. In our project we heavily rely on object literals: we pass them as function parameters and return them from other functions. In many cases these objects tend to be quite complex: with members of different types and several levels of nesting. In our case the overall feeling was that CoffeeScript code was actually harder to read than plain JavaScript code.

  5. Although debugging CoffeeScript turned out to be easier than we expected editing experience has degraded quite a bit. We couldn't find a good editor/IDE for this language. We haven't standardized on editor/IDE for client-side code for our project and in fact we all use different tools. In fact everyone in a team agrees that when they switch to CoffeeScript they get a rather poor support from their tool. IDE and editor plugins are in very early shape and in some cases they can't even give us a proper syntax highlighting or indentation support. Not talking about code snippets or refactoring. We use WebStorm, Eclipse, NetBeans, VisualStudio, Notepad++, and SublimeText2.

  6. Speaking of tools I should mention that CoffeScript compiler itself comes as a Node JS package. We are primary a Java/.NET shop so everybody is developing on Windows boxes. Until recently Windows support was almost non-existent in Node. We couldn't make CoffeeScript compiler running on Windows so for the time being we decided to stick with <script type="text/coffeescript"> tags and browser-based on-the-fly compiler.

    The compiler is quite fast and doesn't increase the startup time much. The downside is that the resulting JavaScript gets evaled and it's a little bit hard to put breakpoints in it in browsers' developer tools (especially in IE8). If we have hard time with the debugging we pre-compile CoffeeScript code with the same migration tool that I listed above but that's still not very convenient.

  7. Other promises of CoffeeScript like automatic var insertion or semi-transparent management of this with fat arrow operator (=>) turned out not giving as much gain as we hoped to. We already use JSLint as part of our build process and we write code in ES3 x ES5-Strict subset of the language. Anyway, the fact that Coffee produces the same kind of "clean" code is a good thing. I wish every server-side framework produced valid HTML5 and CSS3 markup, too!

    That said I wouldn't say that CoffeeScript saves a lot of time by putting var keywords for me. Missing vars are easily caught by JSLint and are easily fixable. Moreover, once you get corrected by it for some time you start writing good JavaScript automatically anyway. Thus I wouldn't say Coffee is really that helpful in this regard.

We evaluated CoffeeScript for about a week. All team members were writing code in it and we shared our experiences with each other. We wrote some new code with it and ported some existing code when we saw fit. Our feelings about the language were mixed.

In general I would say that it didn't sped up our development but it haven't slowed us down either. Some speed gains due to less typing and less error surface were offset by slowdowns in other areas, mostly tool support. After a week we decided that we won't mandate the use of CoffeeScript but we won't prohibit it either. Given a free choice, in practice no one uses it, at least for now. From time to time I think of prototyping some new feature in it and then convert the code to JavaScript before integrating with the rest of the project to get a faster start but I haven't tried that approach yet.

11

Pros

view Trevor Burnham's answer.

plus, you can think of yourself as of hip guy, who is doing trendy stuff, instead of messing with the dirt of javascript.

Cons

CoffeeScript is nothing more than syntactic sugar and pink glasses.

For easy stuff - CoffeeScript is redundant, because doing easy stuff is easy in any language. And jQuery is probably even simpler than CoffeeScript.

For hard stuff - you must understand your medium. And your medium is HTML,DOM and CSS, Javascript is merely a tool to interconnect them, yet - all APIs are written specifically for Javascript. Using other language, which would then be compiled to "real" one - is quite risky, be it Java(GWT), Dart or CoffeeScript.

Anti-patterns or banal ignorance of language rules, can be fixed by reading one-two good books. And im quite sure Coffeescript has its own anti-patterns.

IDE support for Coffeescript is even worse than for JS.

2
7

The biggest pro, in my mind is:

Straightforward coffescript compiles into the javascript you should have written, but didn't, because it wasn't straightforward.

There are some nasty corners of javascript that are only avoided with vigilance -- examples off the top of my head:

  • setting the prototype correctly
  • using === instead of ==
  • checking for null
  • declaring all variables with var
  • wrapping everything in a self-executing anonymous function.

If you write coffeescript, all those are handled for you automatically.

The cons are, IMO, mostly minor:

  • Debugging is a pain
  • There are fewer coffeescript programmers
  • You have to translate documentation from javascript to coffeescript.
3

pros

  1. CoffeeScript has helped me learn more about JavaScript
  2. is fairly easy to read, even for complex nested callbacks
  3. provides safety around some of javascript's difficult to track down language issues

The above working example of Andrew I found to be enlightening. I believe readability of their existing object literal returns would be enhanced by simply manually identify the return

return

// object literal here

The IDE tools have been enhanced, TextMate and Cloud9 support CoffeeScript. Admittedly windows support has been lagging (isn't that true for web development in general though?)

cons

Browser interpreted CoffeeScript can be challenging to debug.

It's an additional layer on top of JavaScript requiring some understanding and consideration from developers.

0

pros

  1. they really optimized the common cases syntatically, in fact, CoffeeScript is one of, if not the most concise language that is "commonly" used http://redmonk.com/dberkholz/2013/03/25/programming-languages-ranked-by-expressiveness/
  2. hides the bad parts of JavaScript (auto-coercion ==, implicit globals, more traditional class system makes common things easier)
  3. extremely easy to learn for Python/Ruby programmers
  4. multi-line anonymous functions + whitespace syntax

cons

  1. removal of var means you can't change an outer-scope variable within an inner scope without using an object, or `var fall_back_to_js;` hacks [why not another assignment statement ':=' which only reassigns a value so obj.naem := 5 typos easier to debug]
  2. you gotta let every tool know about it, unless you want to debug JavaScript :(; btw: you can debug CoffeeScript from Chrome by adding support for source maps; yeoman(npm install yeoman) can help you write a gulp or grunt config file for CoffeeScript
  3. no optional static typing (gotta wait for the next EcmaScript standard)
  4. still need third-party libraries for a module system
  5. syntax traps to be careful of: implicit returns, a b g o means a(b(g(o))), f p, b: 2, c:8 means f(p, {b: 2, c: 8}) rather than f(p, {b: 2}, {c: 8})
  6. doesn't change the broken JavaScript number/type system

Not the answer you're looking for? Browse other questions tagged or ask your own question.