COFFEESCRIPT:
ONLY THE GOOD PARTS
INTRO
# programming language that compiles into JavaScript
# highly influenced by Python and Ruby
# encapsulates JavaScript best practices
rule #1: it's just javascript
# You write this:
do ->
str = "hello world!"
alert str
// Browser sees this:
(function() {
var str = "hello world!";
alert(str);
})();
Your first cup: Basic concepts
# No need for var, no semicolons, scoping becomes intuitive
num = 12
var num;
num = 12;
# Functions resemble C# lambda expressions
foo = (x, y) -> x + y
foo = function(x, y) {
return x + y;
}
# Whitespace is significant
foo = ->
alert "hello world"
x = 15
foo = function() {
return alert("hello world");
}
x = 15;
# var, return, (), [], and ; are often implied
foo bar
opts =
color: "red"
size:
height: 45
width: 150
success: ->
console.log "ok"
foo(bar);
var opts = {
color: "red",
size: {
height: 45,
width: 150
},
success: function() {
console.log("ok");
}
};
# Syntactic shortcuts
x = (y, z) ->
y + z
var x = function(y, z) {
return y + z;
};
coffee = (message="Some Coffee?") ->
answer = confirm message
"Your answer is #{answer}"
var coffee;
coffee = function(message) {
var answer;
if (message == null){
message = "Some Coffee?";
}
answer = confirm(message);
return "Your answer is " + answer;
}
# Designed to look more like a natural language
if light is on then alert "on"
else alert "off"
if (light === true) {
alert("on");
} else {
alert("off");
}
x = 12 unless y
if (!y) {
x = 12;
}
x = if y then 12 else 15
if (y) {
x = 12;
} else {
x = 15;
}
# Designed to reduce common mistakes
if x is 4
if x == 4
if x?
if (x === 4)
if (x === 4)
if (typeof x !== "undefined"
&& x !== null)
Have some sugar with your syntax
# this == @ == this
this.foo()
@.foo()
@foo()
this.foo();
this.foo();
this.foo();
# JavaScript's missing string formatter
alert "#{ a }...#{ b + c }...#{ d }"
alert(a + "..." + (b + c) + "..." + d);
# IIFEs, too
do ($ = jQuery) ->
x = 5
$('div').on 'click', ->
$(@).html x
(function($) {
var x = 5;
$('div').on('click', function() {
$(this).html(x);
});
})(jQuery);
# Loop over collections without writing a novel
alert num for num in [1, 2, 3]
var _arr = [1, 2, 3];
for (var i = 0; i < _arr.length; i++) {
alert(_arr[i]);
}
alert num, i for num, i in {a, b, c}
var _obj = {a: a, b: b, c: c};
for (var i = 0; i < _obj.length; i++) {
alert(_obj[i], i);
}
# Fill and consume lists easily
x = [1..7]
y = [1...7]
plus3 = (z + 3 for z in [1..5])
var x = [1, 2, 3, 4, 5, 6, 7];
var y = [1, 2, 3, 4, 5, 6];
var _arr = [1, 2, 3, 4, 5], plus3 = [];
for (var i = 0; i < _arr.length; i++) {
plus3.push(_arr[i] + 3);
}
# Multi-line strings!
str = """
the quick
brown
fox
"""
str = "the quick \nbrown \nfox";
# Multi-line regex with comments!
regex = ///
\b #word break
limit-
(\d+) #capture this number
///i
regex = /\blimit-(\d+)/i
# Multi-line comments! Okay, not new.
###
But putting comments
in regular expressions
is pretty cool, right?
###
/*
Free haiku with DevSession
*/
Other sweet ingredients
# Compile-time context binding operator
foo = (name) =>
@name = name
var __this = this;
var foo = function (name) {
__this.name = name;
};
# Lexical scoping and variable safety
outer = 1
changeNumbers = ->
inner = -1
outer = 10
inner = changeNumbers()
var changeNumbers, inner, outer;
outer = 1;
changeNumbers = function() {
var inner;
inner = -1;
return outer = 10;
};
inner = changeNumbers();
# Automatic property binding (useful for constructors)
foo = (@a, @b) ->
var foo = function (a, b) {
this.a = a;
this.b = b;
};
//yes, it does the same thing
foo = (options) ->
{@a, @b, @c} = options
var foo = function (options) {
this.a = options.a;
this.b = options.b;
this.c = options.c;
};
# And favorite, the existential operator
a = true if b? and not c?
if ((b != null) && (c == null)) {
a = true;
}
options ?= {}
if (options == null) {
options = {};
}
foo?.bar?.baz?().quux()
if (foo !== null
&& foo.bar != null
&& typeof foo.bar.baz === "function") {
x = foo.bar.baz().quux();
} else {
x = void(0);
}
Splat...variadic functions made easy
# Turn named parameters into arrays
min = (list...) ->
curr = 0
curr = x for x in list when x < curr
curr
alert min a, b, c, d, e
var min = function() {
var i, curr = 0, list = Array.prototype.apply(arguments);
for (i = 0; i < list.length; i++) {
if (list[i] < curr) {
curr = list[i];
}
}
return curr;
};
alert(min(a, b, c, d, e));
# Turn arrays into named parameters
date = (year, month, day) ->
"#{ month }/#{ day }/#{ year }"
arr = [1999, 12, 31]
alert date arr...
var date = function(year, month, day) {
return month + "/" + day + "/" + year;
};
var arr = [1999, 12, 31]
alert(date.apply(null, arr));
And a bunch of other crazy stuff
# Classes and inheritance
class Animal
constructor: (@name) ->
move: (meters) ->
alert @name + " moved #{meters}m."
class Snake extends Animal
move: ->
alert "Slithering..."
super 5
# Aliases
is, ==
inst, !=
not, !
and, &&
or, ||
true, yes, on
false, no, off
x unless y else z
@, this
of
in
a ** b
a // b
a %% b
===
!==
!
&&
||
true
false
!y ? x : z
this
in
//no true JS equivalent
Math.pow(a, b)
Math.floor(a / b)
(a % b + b) % b
Wait! I need decaf
# You can still embed plain JavaScript
if `x == y` then do z
if (x == y) {
z();
}
Coffee goes with everything
# Editors and development tools
- Web Essentials for Visual Studio
- jsFiddle
- CoffeeScript.org
- Cassette
- Js2Coffee
- IntelliJ IDEA
# Add-ons and related projects
- IcedCoffeeScript
- CoffeeKup
CoffeeScript versus TypeScript: Which to Use?
# If you want static type checking and familiar tool support on Visual Studio choose TypeScript# If you want a short learning curve from JavaScript choose TypeScript
# If you want more concise code and lots of syntactic sugar, choose CoffeeScript
# If you are coming from Ruby or Python, CoffeeScript is probably a better match
CoffeeScript: Only The Good Parts
By Bruno Dević
CoffeeScript: Only The Good Parts
- 577