CoffeeScript is a great way to write javascript. It provides many abstractions that simplify the language, and a few syntax niceties that make it much less noisy than pure javascript.
In this introductory talk, we present the language through several examples, looking at many of the features CoffeeScript provides for simplifying the way we write JavaScript. Hopefully in a way that will inspire you to go out and try it!
21. 1st Cup: A simple comparison
var square = function(num) {
return num * num;
}
var list = [1, 2, 3, 4, 5];
var squares = [];
for (var i = 0; i < list.length; i++) {
squares.push(square(list[i]));
}
22. 1st Cup: A simple comparison
var square = function(num) {
return num * num;
}
var list = [1, 2, 3, 4, 5];
var squares = [];
for (var i = 0; i < list.length; i++) {
squares.push(square(list[i]));
}
23. 1st Cup: A simple comparison
var square = function(num) {
return num * num;
}
var list = [1, 2, 3, 4, 5];
var squares = [];
for (var i = 0; i < list.length; i++) {
squares.push(square(list[i]));
}
24. 1st Cup: A simple comparison
var square = function(num) {
return num * num;
}
var list = [1, 2, 3, 4, 5];
var squares = [];
for (var i = 0; i < list.length; i++) {
squares.push(square(list[i]));
}
25. 1st Cup: A simple comparison
var square = function(num) {
return num * num;
}
var list = [1, 2, 3, 4, 5];
var squares = [];
for (var i = 0; i < list.length; i++) {
squares.push(square(list[i]));
}
26. 1st Cup: A simple comparison
square = (num) -> num * num
list = [1..5]
squares = (square n for n in list)
27. 1st Cup: A simple comparison
square = (num) -> num * num
list = [1..5]
squares = (square n for n in list)
28. 1st Cup: A simple comparison
square = (num) -> num * num
list = [1..5]
squares = (square n for n in list)
29. 1st Cup: A simple comparison
square = (num) -> num * num
list = [1..5]
squares = (square n for n in list)
30. 1st Cup: A simple comparison
square = (num) -> num * num
list = [1..5]
squares = (square n for n in list)
57. 3rd Cup: Your Favorite Language
Splats
languagesOfChoice = (langs...) ->
“I like #{langs.join(“, “)}”
58. 3rd Cup: Your Favorite Language
Splats
languagesOfChoice = (langs...) ->
“I like #{langs.join(“, “)}”
languagesOfChoice “Ruby”, “JS”, “Python”
> I like Ruby, JS, Python
59. 3rd Cup: Your Favorite Language
Splats
myLangs = [“Ruby”, “JS”, “Python”]
60. 3rd Cup: Your Favorite Language
Splats
myLangs = [“Ruby”, “JS”, “Python”]
languagesOfChoice myLangs...
> I like Ruby, JS, Python
61. 3rd Cup: Your Favorite Language
Splats
languagesOfChoice = (best, langs...) ->
“I love #{best},
and I like #{langs.join(“, “)}”
62. 3rd Cup: Your Favorite Language
Splats
languagesOfChoice = (best, langs...) ->
“I love #{best},
and I like #{langs.join(“, “)}”
languagesOfChoice “Ruby”, “JS”, “Python”
> I love Ruby, and I like JS, Python
63. 3rd Cup: Your Favorite Language
Splats
languagesOfChoice = (langs..., worst) ->
“I like #{langs.join(“, “)},
but I hate #{worst}”
64. 3rd Cup: Your Favorite Language
Splats
languagesOfChoice = (langs..., worst) ->
“I like #{langs.join(“, “)},
but I hate #{worst}”
languagesOfChoice “Ruby”, “JS”, “PHP”
> I like Ruby, JS, but I hate PHP
65. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
“I love #{best},
and I like #{langs.join(“, “)}”
66. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
“I love #{best},
and I like #{langs.join(“, “)}”
languagesOfChoice “Ruby”
> I love Ruby, and I like
67. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
“I love #{best},
and I like #{langs.join(“, “)}”
languagesOfChoice “Ruby”
> I love Ruby, and I like
languagesOfChoice()
> I love , and I like
68. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
ret = []
if best?
ret.push “I love #{best}”
if langs.length > 0
ret.push “I like #{langs.join(“, “)}”
ret.join(“, and “)
69. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
ret = []
if best?
ret.push “I love #{best}”
if langs.length > 0
ret.push “I like #{langs.join(“, “)}”
ret.join(“, and “)
70. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
ret = []
if best?
ret.push “I love #{best}”
if langs.length > 0
ret.push “I like #{langs.join(“, “)}”
ret.join(“, and “)
71. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
ret = []
if best?
ret.push “I love #{best}”
if langs.length > 0
ret.push “I like #{langs.join(“, “)}”
ret.join(“, and “)
72. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice = (best, langs...) ->
ret = []
if best?
ret.push “I love #{best}”
if langs.length > 0
ret.push “I like #{langs.join(“, “)}”
ret.join(“, and “)
73. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice “Ruby”, “JS”, “Python”
> I love Ruby, and I like JS, Python
74. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice “Ruby”, “JS”, “Python”
> I love Ruby, and I like JS, Python
languagesOfChoice “Ruby”
> I love Ruby
75. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice “Ruby”, “JS”, “Python”
> I love Ruby, and I like JS, Python
languagesOfChoice “Ruby”
> I love Ruby
languagesOfChoice undefined, “Ruby”, “JS”
> I like Ruby, JS
76. 3rd Cup: Your Favorite Language
Existential Operator
languagesOfChoice “Ruby”, “JS”, “Python”
> I love Ruby, and I like JS, Python
languagesOfChoice “Ruby”
> I love Ruby
languagesOfChoice undefined, “Ruby”, “JS”
> I like Ruby, JS
languagesOfChoice()
> “”
77. 3rd Cup: Your Favorite Language
Existential Operator
expr?
78. 3rd Cup: Your Favorite Language
Existential Operator
expr?
typeof expr !== undefined && expr !== null
79. 3rd Cup: Your Favorite Language
Existential Operator
x ?= y
80. 3rd Cup: Your Favorite Language
Existential Operator
x ?= y
x = y unless x?
81. 3rd Cup: Your Favorite Language
Existential Operator
obj = x: { y: 2 }
82. 3rd Cup: Your Favorite Language
Existential Operator
obj = x: { y: 2 }
obj.x?.y
83. 3rd Cup: Your Favorite Language
Existential Operator
obj = x: { y: 2 }
obj.x?.y
if obj.x? then obj.x.y else undefined
84. 3rd Cup: Your Favorite Language
Existential Operator
obj = x: { y: 2 }
obj.x?.y
if obj.x? then obj.x.y else undefined
85. 3rd Cup: Your Favorite Language
Existential Operator
obj = x: { y: 2 }
obj.x?.y
if obj.x? then obj.x.y else undefined
86. 3rd Cup: Your Favorite Language
Existential Operator
obj = x: { y: 2 }
obj.x?.y
if obj.x? then obj.x.y else undefined
87. 3rd Cup: Your Favorite Language
Existential Operator
func?()
88. 3rd Cup: Your Favorite Language
Existential Operator
func?()
func() if typeof func == “function”
89. 3rd Cup: Your Favorite Language
Existential Operator
options.callback?()
156. 6th Cup: Context, the classy way
User = (id, name) ->
this.id = id
this.name = name
this.element = $(“#user-#{this.id}”)
157. 6th Cup: Context, the classy way
Context Accessor
User = (id, name) ->
this.id = id
this.name = name
this.element = $(“#user-#{this.id}”)
158. 6th Cup: Context, the classy way
Context Accessor
User = (id, name) ->
this.id = id
this.name = name
this.element = $(“#user-#{this.id}”)
159. 6th Cup: Context, the classy way
Context Accessor
User = (id, name) ->
this.id = id
this.name = name
this.element = $(“#user-#{this.id}”)
160. 6th Cup: Context, the classy way
Context Accessor
User = (id, name) ->
this.id = id
this.name = name
this.element = $(“#user-#{this.id}”)
161. 6th Cup: Context, the classy way
Context Accessor
User = (id, name) ->
@id = id
@name = name
@element = $(“#user-#{@id}”)
162. 6th Cup: Context, the classy way
Property Arguments
User = (id, name) ->
@id = id
@name = name
@element = $(“#user-#{@id}”)
163. 6th Cup: Context, the classy way
Property Arguments
User = (id, name) ->
@id = id
@name = name
@element = $(“#user-#{@id}”)
164. 6th Cup: Context, the classy way
Property Arguments
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
165. 6th Cup: Context, the classy way
Property Arguments
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
166. 6th Cup: Context, the classy way
Property Arguments
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
167. 6th Cup: Context, the classy way
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
168. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
User.prototype.signOut = ->
$.ajax(...)
169. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
User.prototype.signOut = ->
$.ajax(...)
170. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
User.prototype.signOut = ->
$.ajax(...)
171. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
$(“a.sign-out”, @element).click ->
this.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
172. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
$(“a.sign-out”, @element).click ->
this.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
173. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
$(“a.sign-out”, @element).click ->
this.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
174.
175. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
self = this
$(“a.sign-out”, @element).click ->
self.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
176. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
self = this
$(“a.sign-out”, @element).click ->
self.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
177. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
$(“a.sign-out”, @element).click =>
this.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
178. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
$(“a.sign-out”, @element).click =>
this.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
179. 6th Cup: Context, the classy way
Bound Functions
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
$(“a.sign-out”, @element).click =>
this.signOut()
false
User.prototype.signOut = ->
$.ajax(...)
180. 6th Cup: Context, the classy way
User = (@id, @name) ->
@element = $(“#user-#{@id}”)
User.prototype.signOut = ->
...
181. 6th Cup: Context, the classy way
Classes
class User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
182. 6th Cup: Context, the classy way
Classes
class User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
183. 6th Cup: Context, the classy way
Classes
class User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
184. 6th Cup: Context, the classy way
Classes
class User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
185. 6th Cup: Context, the classy way
Inheritance
class User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
186. 6th Cup: Context, the classy way
Inheritance
class SignedInUser extends User
...
class SignedOutUser extends User
...
187. 6th Cup: Context, the classy way
super
class SignedInUser extends User
constructor: (args...) ->
super args...
$(“a.sign-out”, @element).click =>
this.signOut()
188. 6th Cup: Context, the classy way
On variable locality
class User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
189. 6th Cup: Context, the classy way
On variable locality
class window.User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
190. 6th Cup: Context, the classy way
On variable locality
class window.User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
191. 6th Cup: Context, the classy way
On variable locality
class this.User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
192. 6th Cup: Context, the classy way
On variable locality
class @User
constructor: (@id, @name) ->
@element = $(“#user-#{@id}”)
signOut: ->
...
Here to talk CoffeeScript \nCS is lang generates JS\n***\nBut first: JavaScript\n
Quick Hack: 10 days\nLisp and self, political: C syntax\nBut, web&#x2019;s lingua franca\nSome Good Parts\nSome Not-So-Good Parts\n
Not-So-Good outweigh Good\nCoffee focuses on Good\nHides bad.\n***\nbut first, this is me\n
but first, this is me\nname / location / work\nhere&#x2019;s some javascript\nthere&#x2019;s something very wrong with it\n
\n
\n
\n
there&#x2019;s no var\nme is global\npotentially dangerous\nand a very common mistake\ndon&#x2019;t want to debug sth for 3 hours\nfind out it was you who made the mistake\nvery frustrating\n
fortunately here to talk about cs\ncs has no var keyword :)\n
perfectly valid cs\n*whew*\nin cs all vars are local\nwant global? force it\n***\nhaml\n
cs and haml compared a lot\nboth abstractions\nboth generate known language\n&#x2026;both have significant whitespace\n\n
fns must be indented if span mult lines\nifs and other statements as well\nbut cs also takes advantage w/ obj lit\n***\nignore curlies\n
by making curly braces optional\n
if you indent your keys properly\n
it goes beyond curly braces\nif we write one key:value per line\n
commas are also optional\n
so this is me, in coffeescript\n
just one cup? unacceptable\nstructured in various examples\n
last statement always has implicit return\n***\nif/etc constructs\n
even if last statement is an if, while, etc\n
it always has an implicit return\n***\ndefault args, favorite lang?\n
fns can take def args\n\n
\n
***\noptional parens\n
you prob noticed I call fns w/o ()\n
this is perfectly valid\n
what do you expect will happen?\n
fns are 1st class objects\nreferring to a fn will return the fn obj\n
if the fn takes no arguments\nparens are mandatory\n***\nhaving to choose one lang is unfair\nI like ruby, js, python, lua, coffee&#x2026;\nlet&#x2019;s make our function accept mult args\nalready in js: arguments, but clunky\n
by using ... we tell the function\ntake all args, pass array w/ them to the fn\n
by using ... we tell the function\ntake all args, pass array w/ them to the fn\n***\nsplat when calling\n
let&#x2019;s say we have an array\n
can use splats to expand it to args\n\nbut even if we like a lot of langs\nwe always have a favorite\n
splats can be after arguments\n
***\nbut splats don&#x2019;t need to go at the end\n
as long as you have only one splat\nthey can go anywhere\n
\n
go back to thinking positive\nwhat happens when called with 1 arg?\n
or no args?\n
so let&#x2019;s fix that\nwe need to return both separately\ncheck &#x2018;best&#x2019; -> return I love...\ncheck &#x2018;langs&#x2019; -> return I like...\ndefine array, add each bit iff, join array\n
\n
\n
\n
\n
\n
let&#x2019;s try it\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
***\nranges\n
\n
very much like ruby\nexcept only for numbers\nwe have inclusive ranges\n
and exclusive ranges\n***\nnot only for generating arrays\n
ranges are useful for slicing\n
and they support negative ind\n
\n
\n
\n
\n
assign mult vars at the same time\n
assign mult vars at the same time\n
assign mult vars at the same time\n
1st is matched to the 1st element\n
2nd element is matched to 2nd\n
this works\nwe get what we want\n
but syntax is very noisy\nin fact, it was better before!\n
we match a list to a list\n
\n
\n
\n
assign mult vars at the same time\n
assign mult vars at the same time\n
assign mult vars at the same time\n
assign mult vars at the same time\n
what would happen now?\n
what would happen now?\n
what would happen now?\n
non-splat args always take precedence over splats\n***\nranges&#x2026;pat match is not only meant for arrays\n
we&#x2019;ve an obj literal\nwe want to get the name and age\n
simple, right?\nbut we want pattern matching\n
\n
\n
\n
\n
but still, there&#x2019;s repetition\nvar == key\n
\n
\n
***\ncollections\n
- iterations\n- array comprehensions\n\n
basic iteration on an array\n
you use in for arrays\n
can also iterate over key/val on objects\n
watch out! of for gral objects\n
comprehensions\niterate over a list and do sth with items\n
just a postfix for (almost)\n
also, map\n
or select/filter\n\n
when is equivalent to skipping items\nreturned array only has subset\n***\nif you expanded this into a full for\n
when is equivalent to skipping steps\n
***\nthis\n
<show hands> how many fully understand this?\njavascript has keyword &#x201C;this&#x201D;\nit refers to current &#x201C;evaluation context&#x201D;\nakin to current scope\n
we have a cat\n
\n
\n
\n
\n
this is the receiver when explicit receiver\n
can anyone tell?\n
no receiver: this is top context\n
\n
\n
\n
how does jquery do it?\n
fn.apply\n
&#x201C;this&#x201D; refers to whatever we pass\n***\nfinal cup: context\n
\n
\n
\n
\n
\n
***\ncs takes @ from ruby\n
there&#x2019;s a bit of repetition\n***\nproperty arguments\n
define arguments&#x2026;\n\n
&#x2026; just to assign them to this.whatever\n
shorthand syntax\n
assigns the first argument to this.id\n
assigns the second argument to this.name\n
\n
let&#x2019;s say user has signout fn\n\n
triggers ajax request\nwe don&#x2019;t care about internals\n
trigger by a browser event\n
naive implementation\n
naive implementation\ndoesn&#x2019;t work\n
dom element\n
\n
naive solution\n
naive solution\n
better solution\n
better solution\nforces this inside function\nwraps function so it calls apply\n
***\nlet&#x2019;s disregard the impl\n
pretty, but not idiomatic\nthis looks a lot like a class\n
\n
class keyword\n
constructor function\n
other functions are just nested\nno explicit prototypes\n
user abilities depend on user signed in or not\neg only signed in users can signOut\n
user abilities depend on user signed in or not\nwe can extend User to provide specifics\n
and we can use super\n
CS wraps everything on an ANON FREE fn\nso everything is truly local to the file it&#x2019;s defined on\nnice, but we want classes outside!\n\n\n
global class\n\n
anon free fn => this is window\n\n
anon free fn => this is window\n\n
you can use @\n\n
\n
\n
\n
you tell me :)\n\n
there&#x2019;s a large community\n
big names using it like 37s\n
\n
\n
\n
\n
\n
\n
let&#x2019;s take this simple for loop\n
suppose we need timeouts\nwe wrap it in a function\nbut&#x2026;\n