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...


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:


Encourages the use of good JavaScript patterns
Discourages JavaScript anti-patterns
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:


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.)
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).
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.
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.
