CoffeScript Quick On
November 13, 2014
This is a note from the lucid tutorial Essence of CoffeeScript to get a quick glance of CoffeeScript. The headings and examples are taken from there, but I added some thing I think worth mentioning.
Key Fundamentals
Punctuation is usually optional, so skip it ;}),
- Function calls don’t need parentheses.
- String concatination is the same as Javascript.
- Javascript objects like console are still usable.
nickname = prompt "what's your nickname?"
console.log 'Hi ' + nickname
Use indentation instead of curly braces
if
statement doesn’t need parenthese.- Indentation instead of
{}
. - String interpolation in the notation of
"#{now}"
.
date = new Date()
hour = date.getHour()
if hour > 17
now = 'night'
else
now = 'day'
console.log 'It is now #{now} time.'
Every expression returns a value
- A single variable or literal constant like the
'night'
and'day'
in theif
statement above returns itself. if
statement returns the value returned by the last child statment in the selected branch. True for other statements too.
date = new Date()
hour = date.getHours()
now = if hour > 17 then 'night' else 'day'
console.log "It is now #{now} time."
Never specify var
- Every variable is made local by implicitly adding a
var
in the front. This saves programmers a lot from the danger mixing up local and global variables. - Using
var
explicitly is actually forbidden – you’ll get a compile error.
Some Useful Tips
Read a line from right to left
console.log 'Hi ' + prompt "What's your nickname?"
Use punctuation wherever it adds readability
console.log 'Hi ' + (prompt "What's your nickname?")
console.log 'Hi ' + prompt("What's your nickname?")
Object literals are all over the place
- Become familiar with an object literal (or hash) without its punctuation.
- The : indicates a key: value pair.
- Key value pairs need to be separated with a comma when on the same line.
- Key value pairs don’t need comma separation when on their own line.
- Key value pairs that belong to the same hash are indented at the same level.
options = readonly: true, theme: 'solarized'
theme =
color:
text: 'blue'
background: 'white'
font:
family: 'SourceCode Pro'
size: '16px'
console.log 'options are ', options
A Function Is This Way ->
Use dash rocket ->
to define a function
- Anonymous functions (closures?) are used quite commonly.
- Use the
(arg) -> body
notation.
reportStatus = (msg) -> console.log 'Status: ', msg
reportStatus 'ok'
A function with no arguments doesn’t need ()
- Get used to this (a bit weird?) notation.
- Notice that
()
is needed to call the function, but not to define it.
getHostname = -> console.log location.hostname
getHostname()
A function automatically returns its final value
getHostname = -> location.hostname
console.log getHostname()
Indent the function body
reportRootURL = ->
protocol = location.protocol
hostname = location.hostname
console.log "#{protocol}//#{hostname}"
reportRootURL()
Get used to passing a function
quoteCallback = (quote)-> console.log quote
apiEndpoint = 'https://api.github.com/zen'
jQuery.get apiEndpoint, quoteCallback
Some Conditional Love
The body of an if can come first
timeOfDay = 'morning' if hour < 11
This could come in handy.
Use unless to flip an if else
unless
runs the statement only if the condition is untrue.
askForGeoLocation = ->
return alert 'Seriously? You gotta update your browser!' unless navigator.geolocation
alert 'Your browser is about to ask you to allow geolocation'
navigator.geolocation.getCurrentPosition positionCallback
positionCallback = (position)->
point = position.coords
console.log "Lat: #{point.latitude}, Lng: #{point.longitude}"
askForGeoLocation()
The Existential ?
Operator
Use ?
to check if something exists
?
checks for the existence of the preceeding variable and producestrue
if it does andfalse
otherwise.- Note that using a non-existing variable (equals
undefined
) is a syntax error and cannot even be used for the condition inif
statements, while a variable equalsnil
does exist.:w ?
can be used to avoid errors all together.
console.log 'unicorns are not real!' unless unicornsExist
console.log 'unicorns are not real!' unless unicornsExist?
unicornsExist = false
console.log 'unicorns are real!' if unicornsExist
console.log 'unicorns are real!' if unicornsExist?
Use ?
to set default values
a ?= b
means “if a
doesn’t exist, create it and initialize it using b
; but if it does, do nothing”. This is a great method to set default value.
setProfile = (profile)->
profile ?= {}
profile.name ?= 'guest'
console.log 'profile:', profile
setProfile()
setProfile age: 25
setProfile name: 'misty'
Use ?
to call a function only if it exists
foo?()
means “call function foo
if it exists, otherwise do nothing”.
barn =
horse:
run: ()-> 'gallop' for i in [0..3]
console.log barn.horse.run()
console.log barn.horse.fly()
console.log barn.horse.fly?()
Use ?
to soak up errors in chain
The last line above means “if p
exists, and it has a method run
, then call it”. Notice the second last line produces error.
barn =
horse:
run: ()-> 'gallop' for i in [0..3]
h = barn.horse
p = barn.pig
console.log h.run?()
console.log h.fly?()
console.log p.run?()
console.log p?.run?()
Some Loopy Situations
Use in
to loop through an array
- Create a range using something like
[0..9]
. for item in array
like in some other languages.
printDigits = ()->
digits = [0..9]
for digit in digits
console.log 'digit: ', digit
Use of
to loop through a hash
reportTheme = ()->
theme = text: 'blue', button: 'red'
for key, value of theme
console.log "#{key} is set to #{value}"
The body of a loop can come first
digits = [0..9]
console.log i for i in digits
theme = {text: 'blue', button: 'red'}
console.log key,'=', val for key,val of theme
A loop retuns an array
oddDigits = (1 + i*2 for i in [0..4])
This is called “array comprehension” like in Python.
Working With Class
Defining a class is simple
- Use
class
to define a class. - Use
new
to create an instance.
class Mutant
fight: (badGuy)-> 'Spin a Web onto ' + badGuy
spidy = new Mutant
spidy.fight('Lizard')
this
has an alias: @
- Writing
@method
is actuall writingthis.method
. this
or@
refers to the class that we’re defining.
class Mutant
superPower: 'do nothing'
fight: (badGuy)-> @superPower + ' onto ' + badGuy
spidy = new Mutant
spidy.fight('Boomerang')
spidy.superPower = 'Spin web'
spidy.fight('Boomerang')
Use a constructor for initialization
- Constructor is defined by the
constructor
element function. - Initialize the instance by passing arguments to the
new
statement.
class Mutant
superPower: 'do nothing'
constructor: (power) -> @superPower = power
fight: (badGuy)-> @superPower + ' onto ' + badGuy
spidy = new Mutant 'spin web'
spidy.fight 'SandMan'
Inheriting from a Class is Simple
- Define subclass by saying that the child
extend
s the father. - Call superclass’s constructor by
super
.
class Mutant
superPower: 'do nothing'
constructor: (power) -> @superPower = power
fight: (badGuy)-> @superPower + ' onto ' + badGuy
class NinjaTurtle extends Mutant
constructor: () ->
super('Kung Fu')
raphael = new NinjaTurtle
raphael.fight('Shredder')