CoffeeScript Protips
Making Life a Little Easier
Here’s some pro tips I’ve gathered up from my experiences with CoffeeScript. Hopefully it’ll help you get up to speed with the language a lot faster.
To the reader: a lot of these tips are style guides, and not hard rules. It does help to have a starting point but if something else feels more comfortable then by all means, do it that way! The most important thing is to keep everything consistent within the same project.
Use setTimeout a lot? This one is a major syntax-saver:
timeout = (delay, cb) -> setTimeout cb, delay
It turns this ugliness:
setTimeout ->
doSomeStuff()
setTimeout ->
fml()
, 200
, 500
Into this hotness:
timeout 500, ->
doBetterStuff()
timeout 200, ->
yay()
The awkward trailing delay at the end of the anonymous function block makes it hard to see what the delay is, especially if you’re chaining a bunch of anonymous functions.
Stuck in the debugger? Look at _this.
When debugging compiled CoffeeScript code in a function that uses the fat arrow function binding (=>), the keyword “this” or “@” actually refers to “_this” in the compiled JavaScript.
You are using the fat arrows, right? Quit making “self”ies.
CoffeeScript:
helper = (person) =>
@helpOut person
Compiled JavaScript:
var helper,
_this = this;
helper = function(person) {
return _this.helpOut(person);
};
Exception to the rule: When using fat arrows in classes, the compiler behaves differently and will “__bind” your prototype functions to the correct context, so that “this” works as normal. Class methods are not bound at all, with “this” instead referring to the class constructor directly.
CoffeeScript:
class MyClass
@classFn: =>
@doSomething()
protoFn: =>
@somethingElse()
Compiled JavaScript:
var MyClass,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
MyClass = (function() {
function MyClass() {
this.protoFn = __bind(this.protoFn, this);
}
MyClass.classFn = function() {
return MyClass.doSomething();
};
MyClass.prototype.protoFn = function() {
return this.somethingElse();
};
return MyClass;
}).call(this);
Use functional programming.
You can easily accomplish this with either Underscore or LoDash.
There are a lot of cool things that CoffeeScript can do with loop comprehensions that keep you from writing verbose for loops. It’s a great feature, don’t get me wrong, but it doesn’t help much with the verbosity once it’s compiled to JavaScript.
CoffeeScript:
dragon.breatheFire() for dragon in dragonHorde
Compiled JavaScript:
var dragon, _i, _len;
for (_i = 0, _len = dragonHorde.length; _i < _len; _i++) {
dragon = dragonHorde[_i];
dragon.breatheFire();
}
Huh. That looks decidedly less sexy and even a bit heavier than just writing vanilla JavaScript, isn’t it? Using a library like LoDash, however, you can write this:
_.forEach dragonHorde, (dragon) -> dragon.breatheFire
That avoids generating the for loop because LoDash takes care of the iteration.
WARNING: Always know that you’re optimizing for.
In this case, we’re optimizing for code complexity and code size, not execution speed. If you use this throughout a large project where you do a lot of iterating over small arrays this is great. If the loop is performance-sensitive you will want to use the comprehension syntax because nothing really beats the for loop implementation. When in doubt, benchmark and profile your code!
The point here is, opt for the functional style as a default before worrying about optimization. There are cases where it’s faster, and cases where it’s not. Functional programming, however, does tend to be less bug-ridden and leads itself to great levels of abstraction through the identification of higher order functions. If that made your head spin, give this a read: http://eloquentjavascript.net/chapter6.html
“&& ||”? “and or”? Doesn’t matter, but stick with the most familiar one.
When in doubt about which boolean operators to use, stick with the one that feels most comfortable to you. In multi-language projects, the best thing would be to stick with what the other languages use. For example, if your backend is in Ruby, Python, etc. you should should use “and or”. If it’s Java, C++, etc. you should use “|| &&”. The goal? Less culture shock when you switch languages.
(Parentheses)? {Braces}?
Skip em. Seriously. Avoid them at all costs — being able to omit them is one of the main features of the language and you’ll learn to love it. There are, of course, some border cases where you have to use them. Here’s my (personal) preference with examples:
jQuery/LoDash:
$('#selector').trigger 'click'
$('.something').clear()
_(myObject).extend otherObject
# but with Underscore this is preferred:
_.extend myObject, otherObject
Chained function calls:
_(chainMe)
.filter(filterFunction)
.map(mapFunction)
.apply(something)oneLineChains().areOk('but').onlyWhenShort()
Small inline object as a function argument:
say 'hello', {with: 'gusto'}, 100
For sake of example, here’s how you should style multi-line arrays:
pirates =
[
'Bok Choy'
'Arrr Dewis'
'Matey Flynn'
]
Did you notice that there’s no commas? Good.
Abuse @.
This one might be controversial. I argue to not use the keyword “this” at all. Any time you think you’re going to use “this”, use “@” instead. Four or five less letters each time really adds up in a big project. What’s better is that some syntax highlighters will recognize “@myVar” and color the whole thing, as opposed to just coloring the word “this” in “this.myVar”. You’ll find that you don’t need “this” after a while.
If you hate your keyboard and my advice, go ahead and use “this”, it won’t kill anyone. But be sure to say hi to Java for me.