I recently wrote a piece comparing CoffeeScript, TypeScript and Dart. For the UI component of Wellmo, we decided upon using CoffeeScript. While this has been a great leap from JavaScript, we’ve had our share of setbacks. Here’s a few issues that are good to know about when using CoffeeScript.
Fat vs thin
This one has definitely bitten everyone who has used CoffeeScript one time or another. Keeping track of what this
is pointing to and when you need to use the fat arrow => instead of the thin arrow -> is sometimes a tricky business. You’re tempted to use the fat arrow always for simplicity, but then you’re paying a price in performance.
Accidental returns
CoffeeScript automatically returns the result of the last statement within a function, just like Ruby. Personally I like this feature, but it has caused some surprises. We use promises extensively, and when a function in a promise chain returns a promise, that promise is automatically added as part of the promise chain.
We’ve had a few cases where a function that shouldn’t have any meaningful return value accidentally returns a promise. This in turn is inadvertently injected into a promise chain where it shouldn’t be. This took a while to figure out, and is something to watch out for. If a function does not have any meaningful return value, you may want/need to add a null
on the last line to prevent accidental returns.
Almost-optional parenthesis
Another trait borrowed from Ruby is optional parenthesis. While this is another feature I like in general, it is a poor fit for JavaScript, where functions are first-class citizens. The problem is that parenthesis are optional, except if there are no arguments. Without arguments or parenthesis, it’s a function reference, not a function call. I can’t count the number of times I’ve been bitten by this one.
We’ve even considered mandating usage of parenthesis in all code, but I don’t really like such mandates either.
JavaScript woes
While CoffeeScript fixes many of JavaScript’s bad parts, many are still present and you need to be aware of them. After all, It’s just JavaScript! Just recently we discovered that a model that we thought contained a number actually contained a string, which was being automatically coerced.
Developing language
After using other languages, it came as a slight surprise that CoffeeScript is still a language in development. We had a mysterious issue where the same code built successfully on some machines, but not on others. We discovered that catching errors without naming the error was introduced in 1.6.3, while one of our developers still had 1.6.2.
Conclusion
Web development is transforming as we speak. There are a lot of altJS languages cropping up, all with their strengths and weaknesses.
Many of the problems I listed above are inherent of JavaScript, and not hidden because CoffeeScript is ultimately a thin conversion layer between the languages. This is one of CoffeeScript’s biggest strengths and weaknesses.
I doubt we’ll be using CoffeeScript in ten years’ time, but at the moment it’s a very viable alternative. You just need to be aware of the pitfalls. Even with its shortcomings, I still consider it the correct choice for our application.
Pingback: CoffeeScript vs. TypeScript vs. Dart | Code for Hire
Would you use CoffeeScript today, if you were starting an app from scratch?
For our current project, yes. I do believe it is a good balance of cleaner syntax, less noise, and hiding of JavaScript’s bad parts, yet providing full flexibility and power. But it’s by no means a perfect language (largely due to its heritage).
For other types of projects I might consider other alternatives. See the end summary of the CoffeeScript vs TypeScript vs Dart article for some ideas.
Do you think TypeScript has a brighter future than CoffeeScript? What about Dart? How do you think the future with be for the three languages you’ve reviewed in the past article?
TypeScript is an evolution over JavaScript. That’s why it has a much lower barrier of entry. I believe it may well pick up, especially if the ECMAScript standard progresses in its direction. However it will forever bear some of the icky remnants of JavaScript.
Dart is a revolution. I’d really want it to succeed – from what I read (which was admittedly very little), it seemed like a very well-thought-out language. But it has a much higher barrier to get it rolling.
I don’t see CoffeeScript’s fate as poor either. It’s filling a need. Maybe that need will disappear in the future, and people migrate to other languages. Or maybe CoffeeScript will also evolve into something new.
Both TypeScript and Dart are verbose languages with a rigid syntax, made to be easily accessible. CoffeeScript is very terse. There’s a trend on trying to find more succinct languages, especially among expert coders.
Consider Java and Scala: For a team of ten excellent coders, Scala may be more efficient. But if you have a thousand mediocre coders, I’d place my bets on Java. I think the development of this trend – one way or the other – will have a markable effect on what languages will be used in the future.
“Just recently we discovered that a model that we thought contained a number actually contained a string”
TypeScript probably would have helped here
Pingback: 1p – CoffeeScript woes (2013) – blog.offeryour.com
Pingback: 1p – CoffeeScript woes (2013) – Exploding Ads
I started using CoffeeScript about a year ago. I just ran through the Angular 2 tutorial last week using TypeScript. I have to say I’m really not a fan of TypeScript! If you want to make JavaScript more unpleasant, use TypeScript. I’m a Python developer though so I prefer significant whitespace and dynamic typing. Also, I haven’t really run into any of the woes you’ve described – probably because of my own style guidelines. I’m not a fan of ruby magic so I prefer to always use parenthesis. I’ve never used fat arrows. I guess the automatic return has bitten me a few times, but most of the time I am conscious of it now. One thing that did bite me that took a while to figure out was to use @var when I didn’t want CoffeScript to declare a new variable, but rather use a global variable. Ran into that issue while doing a meteor tutorial – but writing it in CoffeeScript rather that JavaScript.