Upgrade to Pro — share decks privately, control downloads, hide ads and more …

An Evening with CoffeeScript

An Evening with CoffeeScript

Slides for http://evening.coffeescript.io/

Javascript has become one of the most popular languages on the web but it still suffers to date from poor and hasty design decisions made during it’s infancy.

CoffeeScript — a fairly new language inspired by Ruby, Python and Haskell — compiles into Javascript, aims to highlight Javascript’s good parts while hiding its “dark sides” and to make the whole Javascript experience just that much more enjoyable.

This (free) course will teach a basic understanding of the language as well as attempt to clear out some of the misunderstandings that seem to keep people from integrating CoffeeScript into their workflow.

In the first part, the attendees will learn the fundamental concepts behind CoffeeScript as well as discover some of the existing tools.

The second part — an interactive workshop — will show CoffeeScript in action. Attendees are invited to try their newly earned skills on a small application and to hopefully discover the ‘power of CoffeeScript’.

Florian Plank

June 13, 2013
Tweet

More Decks by Florian Plank

Other Decks in Programming

Transcript

  1. An evening
    with
    CoffeeScript

    View Slide

  2. The evening

    View Slide

  3. The evening
    What is CoffeeScript
    How to use it
    Concepts
    CoffeeScript 101

    View Slide

  4. The evening

    View Slide

  5. The evening
    Hands–on
    Workshop

    View Slide

  6. number = 42
    var number = 42;

    View Slide

  7. number = 42
    var number = 42;

    View Slide

  8. CoffeeScript

    View Slide

  9. “The assembly language
    of the web.”

    View Slide

  10. http://www.flickr.com/photos/nathansmith/4704268314/

    View Slide

  11. Javascript: The Quirky Parts

    View Slide

  12. typeof null

    View Slide

  13. typeof null
    // "object"

    View Slide

  14. 0, NaN, "", false, null, undefined

    View Slide

  15. var numbers = ['10','10','10'];
    numbers.map(parseInt);

    View Slide

  16. var numbers = ['10','10','10'];
    numbers.map(parseInt);
    // [10, NaN, 2]

    View Slide

  17. array.map(callback[, thisArg])
    callback(value[, index[, array]])
    parseInt(string, radix);

    View Slide

  18. array.map(callback[, thisArg])
    callback(value[, index[, array]])
    parseInt(string, radix);

    View Slide

  19. array.map(callback[, thisArg])
    callback(value[, index[, array]])
    parseInt(string, radix);

    View Slide

  20. var numbers = ['10','10','10'];
    parseInt('10', 0, numbers); // 10 (decimal)
    parseInt('10', 1, numbers); // NaN
    parseInt('10', 2, numbers); // 2 (binary)

    View Slide

  21. “Exactly which radix is chosen
    [by default] is implementation-
    dependent.”

    View Slide

  22. var numbers = ['10','10','10'];
    parseInt('10', 0, numbers); // 10 (decimal)
    parseInt('10', 1, numbers); // NaN
    parseInt('10', 2, numbers); // 2 (binary)

    View Slide

  23. [1, 71, 4, 5609, 102].sort()

    View Slide

  24. [1, 71, 4, 5609, 102].sort()
    # => [1, 102, 4, 5609, 71]

    View Slide

  25. [1, 71, 4, 5609, 102].sort(function(a, b){
    return a - b;
    });

    View Slide

  26. ['a', 'b', 'c'].join()

    View Slide

  27. ['a', 'b', 'c'].join()
    # => "a,b,c"

    View Slide

  28. abstract boolean break byte case catch char class const
    continue debugger default delete do double else enum
    export extends false final finally float for function
    goto if implements import in instanceof int interface
    long native new null package private protected public
    return short static super switch synchronized this throw
    throws transient true try typeof var volatile void while
    with

    View Slide

  29. abstract boolean break byte case catch char class const
    continue debugger default delete do double else enum
    export extends false final finally float for function
    goto if implements import in instanceof int interface
    long native new null package private protected public
    return short static super switch synchronized this throw
    throws transient true try typeof var volatile void while
    with

    View Slide

  30. View Slide

  31. ;

    View Slide

  32. http://davidwalsh.name/javascript-semicolons

    View Slide

  33. a = b + c
    (d + e).print()

    View Slide

  34. a = b + c(d + e).print();

    View Slide

  35. function add() {
    var a = 1, b = 2
    return
    a + b
    }

    View Slide

  36. function add() {
    var a = 1, b = 2;
    return;
    a + b;
    }

    View Slide

  37. View Slide

  38. “Expose the good parts of
    JavaScript in a simple way”

    View Slide

  39. <>

    View Slide

  40. .js
    <>

    View Slide

  41. <>

    View Slide

  42. <>

    View Slide

  43. .js
    <>

    View Slide

  44. .js
    .coffee

    View Slide

  45. .js
    .coffee

    View Slide

  46. .js
    .coffee

    View Slide

  47. Compiler

    View Slide

  48. .js
    .coffee
    .litcoffee

    View Slide

  49. .js
    .coffee
    .litcoffee

    View Slide

  50. Publish via rsync
    -----------------
    Publishing is nice and rudimentary. We build out an entirely static version
    of the site and **rysnc** it up to the server.
    Journo.publish = ->
    do Journo.build
    rsync 'site/images/', path.join(shared.config.publish, 'images/'), ->
    rsync 'site/', shared.config.publish
    A helper function for **rsync**ing, with logging, and the ability to wait
    for the rsync to continue before proceeding. This is useful for ensuring
    that our any new photos have finished uploading (very slowly) before the
    update to the feed
    is syndicated out.
    https://github.com/jashkenas/journo/blob/master/journo.litcoffee

    View Slide

  51. Usage

    View Slide

  52. Installation (v1.6.3)

    View Slide

  53. sudo npm install -g coffee-script
    Installation (v1.6.3)

    View Slide

  54. Executable
    $ coffee --compile file.coffee
    $ coffee --watch --compile --output js cs/*.coffee
    $ coffee -wco js cs
    $ coffee --map
    $ coffee --bare

    View Slide

  55. Interactive REPL
    $ coffee
    coffee> a = [1..3]
    a = [1..3]
    [ 1, 2, 3 ]

    View Slide

  56. Script tags

    <br/>

    View Slide

  57. Build tools

    View Slide

  58. Source maps

    View Slide

  59. Concepts

    View Slide

  60. It’s just JavaScript

    View Slide

  61. Readability
    Natural language

    View Slide

  62. Fast

    View Slide

  63. Backward compatible

    View Slide

  64. Sturdy

    View Slide

  65. Overview

    View Slide

  66. Whitespace sensitive
    user =
    name: "John"
    age: 23

    View Slide

  67. ;

    View Slide

  68. View Slide

  69. Whitespace sensitive
    user = name: "John", age: 23; tasks = []

    View Slide

  70. var*

    View Slide

  71. *

    View Slide

  72. {}*

    View Slide

  73. *

    View Slide

  74. Whitespace sensitive
    user =
    name: "John"
    age: 23
    try
    failwhale()
    catch e
    console.error e.message

    View Slide

  75. ()*

    View Slide

  76. *

    View Slide

  77. Function invocation
    console.error e.message
    console.error JSON.stringify e
    console.error(e.message)
    console.error(JSON.stringify(e))

    View Slide

  78. Everything is an expression

    View Slide

  79. Work in every JavaScript runtime

    View Slide

  80. h p://try.coffeescript.io/

    View Slide

  81. Assignments

    View Slide

  82. name = "John"
    age = 23

    View Slide

  83. // Generated by CoffeeScript 1.3.3
    (function() {
    var age, name;
    name = "John";
    age = 23;
    }).call(this);

    View Slide

  84. Lexical Scope & variable safety

    View Slide

  85. function setA() {
    a = 1;
    }
    function setB() {
    var b = 2;
    }
    setA()
    console.log(a)
    # => 1
    setB()
    console.log(b)
    # => ReferenceError: b is not defined

    View Slide

  86. Destructuring assignment

    View Slide

  87. [name, age] = ["John", 23]

    View Slide

  88. var age, name, _ref;
    _ref = ["John", 23], name = _ref[0], age = _ref[1];

    View Slide

  89. name = "John"
    user = {name}
    var name, user;
    name = "John";
    user = {
    name: name
    };

    View Slide

  90. response = name: "John", email: "[email protected]", age: 23
    {name, age} = response
    var age, name, response;
    response = {
    name: "John",
    email: "[email protected]",
    age: 23
    };
    name = response.name, age = response.age;

    View Slide

  91. try
    failwhale()
    catch {line, message}
    displayError "Error on line #{line}: #{message}"
    var line, message;
    try {
    failwhale();
    } catch (_error) {
    line = _error.line, message = _error.message;
    displayError("Error on line " + line + ": " + message);
    }

    View Slide

  92. Comments

    View Slide

  93. # Somehow this causes problems:
    realAge = age / 0

    View Slide

  94. ###
    Doomsday device
    Author: John Doe
    Last updated: 12.12.2012
    ###
    /*
    Doomsday device
    Author: John Doe
    Last updated: 12.12.2012
    */

    View Slide

  95. Arrays

    View Slide

  96. numbers = [14, 8, 15, 16, 23, 42]

    View Slide

  97. pixels = [
    255, 0, 255, 255 # first pixel
    0, 0, 0, 0 # second pixel
    255, 255, 0, 255 # third pixel
    ]

    View Slide

  98. users = [
    name: "John"
    age: 23
    ,
    name: "Dirk"
    age: 45
    ]

    View Slide

  99. var users;
    users = [
    {
    name: "John",
    age: 23
    }, {
    name: "Dirk",
    age: 45
    }
    ];

    View Slide

  100. users = [{
    name: "John"
    age: 23
    }, {
    name: "Dirk"
    age: 45
    }]

    View Slide

  101. Ranges

    View Slide

  102. numbers = [1..10]
    var numbers;
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    View Slide

  103. numbers = [1..100]
    var numbers, _i, _results;
    numbers = (function() {
    _results = [];
    for (_i = 1; _i <= 100; _i++){ _results.push(_i); }
    return _results;
    }).apply(this);

    View Slide

  104. numbers = [1..10]
    numbers[3..6]
    # => [4, 5, 6, 7]
    var numbers;
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    numbers.slice(3, 7);

    View Slide

  105. numbers = [1..10]
    numbers[7..]
    # => [8, 9, 10]
    var numbers;
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    numbers.slice(7);

    View Slide

  106. numbers = [1..10]
    numbers[..]
    # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    var numbers;
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    console.log(numbers.slice(0));

    View Slide

  107. Objects

    View Slide

  108. user = {name: "John", age: "John"}

    View Slide

  109. user = name: "John", age: "John"

    View Slide

  110. users =
    name: "John"
    age: 23

    View Slide

  111. users =
    name:
    first: "John"
    last: "Doe"
    age: 23
    hobbies: []

    View Slide

  112. $('#logo').attr class: 'bigger'
    $('#logo').attr({
    "class": 'bigger'
    });

    View Slide

  113. console.log animal.class
    console.log(animal["class"]);

    View Slide

  114. Strings

    View Slide

  115. firstName = "John"
    lastName = 'Doe'
    var firstName, lastName;
    firstName = "John";
    lastName = 'Doe';

    View Slide

  116. Interpolation

    View Slide

  117. greeting = "Welcome back, #{name}"
    var greeting;
    greeting = "Welcome back, " + name;

    View Slide

  118. greeting = "#{30 - user.age} years until 30!"
    var greeting;
    greeting = "" + (30 - user.age) + " years until 30!";

    View Slide

  119. age = 27
    ageString = "#{age}"
    var age, ageString;
    age = 27;
    ageString = "" + age;

    View Slide

  120. Multiline strings

    View Slide

  121. story = "Some people go batshit crazy
    if your code exceeds 80 columns per
    line so yo better just don't do."
    var story;
    story = "Some people go batshit crazy if your code ↵
    execeds 80 columns per line so yo better just don't ↵
    do.";

    View Slide

  122. Block strings

    View Slide

  123. headerMarkup = """

    XML is like violence

    """
    var headerMarkup;
    headerMarkup = "\n XML is like ↵
    violence\n";

    View Slide

  124. Regular expressions

    View Slide

  125. mastercard = /5[1-5][0-9]{14}/
    var mastercard;
    mastercard = /^5[1-5][0-9]{14}$/;

    View Slide

  126. mastercard = /// ^
    5[1-5] # starts with 51..55
    [0-9]{14} # 14 more digits
    $ ///
    var mastercard;
    mastercard = /^5[1-5][0-9]{14}$/;

    View Slide

  127. Functions

    View Slide

  128. function fullName(user) {
    return user.firstName + ' ' + user.lastName;
    }
    var fullName = function(user) {
    return user.firstName + ' ' + user.lastName;
    }

    View Slide

  129. fullName(user);
    function fullName(user) {
    return user.firstName + ' ' + user.lastName;
    }
    "John Doe"

    View Slide

  130. fullName(user);
    var fullName = function(user) {
    return user.firstName + ' ' + user.lastName;
    }
    TypeError: undefined is not a function

    View Slide

  131. functionName = -> functionBody
    functionName = ->
    functionBody

    View Slide

  132. functionName = -> functionBody
    functionName = ->
    functionBody

    View Slide

  133. var functionName;
    functionName = function() {
    return functionBody;
    };

    View Slide

  134. Invocation

    View Slide

  135. outer inner
    outer(inner)
    outer inner 'foo', 'bar'
    wrap outer inner core
    outer(inner);
    outer(inner);
    outer(inner('foo', 'bar'));
    wrap(outer(inner(core)));

    View Slide

  136. Arguments

    View Slide

  137. fullName = (firstName, lastName) ->
    "#{firstName} #{lastName}"

    View Slide

  138. Default values

    View Slide

  139. fullName = (firstName, lastName = "Doe") ->
    "#{firstName} #{lastName}"

    View Slide

  140. var fullName;
    fullName = function(firstName, lastName) {
    if (lastName == null) {
    lastName = "Doe";
    }
    return "" + firstName + " " + lastName;
    };

    View Slide

  141. Splats

    View Slide

  142. invited = (names...) ->
    "Invited: #{names.join(', ')}"
    invited "John", "Mary", "The boy"

    View Slide

  143. var invited,
    __slice = [].slice;
    invited = function() {
    var names;
    names = 1 <= arguments.length ? ↵
    __slice.call(arguments, 0) : [];
    return "Invited: " + (names.join(', '));
    };

    View Slide

  144. Closures

    View Slide

  145. makeAdder = (x) -> (y) -> x + y
    add5 = makeAdder(5)
    add5(10) # => 15
    var makeAdder;
    makeAdder = function(x) {
    return function(y) {
    return x + y;
    };
    };

    View Slide

  146. do ->
    do (argument) ->
    (function() {})();
    (function(argument) {})(argument);

    View Slide

  147. Conditionals

    View Slide

  148. if name == 'John'
    console.log "It's John again."
    else if name == 'Marcy'
    console.log "It's Marcy this time."
    else
    console.log "It's not John."
    unless name == 'John'
    console.log "It's someone else"

    View Slide

  149. if (name === 'John') {
    console.log("It's John again.");
    } else if (name === 'Marcy') {
    console.log("It's Marcy this time.");
    } else {
    console.log("It's not John.");
    }
    if (name !== 'John') {
    console.log("It's someone else");
    }

    View Slide

  150. if name == 'John' then console.log "It's John again."

    View Slide

  151. Postfix

    View Slide

  152. console.log "It's John again." if name == 'John'
    console.log "It's someone else" unless name == 'John'

    View Slide

  153. Everything’s an expression

    View Slide

  154. message = if name == 'John'
    "It's John again."
    else if name == 'Marcy'
    "It's Marcy this time."
    else
    "It's not John."
    console.log message

    View Slide

  155. message =
    if name == 'John' then "It's John again."
    else if name == 'Marcy' then "It's Marcy this time."
    else "It's not John."
    console.log message

    View Slide

  156. [lastName, age] =
    if name == 'John' then ['Doe', 23]
    else if name == 'Marcy' then ['Murcy', 29]
    else ['Unknown' ]
    console.log lastName, age

    View Slide

  157. Ternary

    View Slide

  158. var isJohn = name == 'John' ? 'yep' : 'nope';

    View Slide

  159. isJohn = if name == 'John' then 'yep' else 'nope'

    View Slide

  160. var isJohn;
    isJohn = name === 'John' ? 'yep' : 'nope';

    View Slide

  161. (›°□°ʣ›ớ ᵲᴸᵲ

    View Slide

  162. “I realize its slightly longer, but
    less cryptic, I hope.”
    — Jeremy Ashkenas

    View Slide

  163. Operators and aliases

    View Slide

  164. isJohn = if name is 'John' then 'yep' else 'nope'

    View Slide

  165. is ===
    isnt !==
    not !
    and &&
    or ||
    true, yes, on true
    false, no, off false
    @, this this
    of in
    in

    View Slide

  166. is ===
    isnt !==
    not !
    and &&
    or ||
    true, yes, on true
    false, no, off false
    @, this this
    of in
    in

    View Slide

  167. is ===
    isnt !==
    not !
    and &&
    or ||
    true, yes, on true
    false, no, off false
    @, this this
    of in
    in

    View Slide

  168. letIn() if name in ['John', 'Marcy']

    View Slide

  169. letIn() if name in ['John', 'Marcy']
    if (name === 'John' || name === 'Marcy') {
    letIn();
    }

    View Slide

  170. Existential operator

    View Slide

  171. invite(user) if user?

    View Slide

  172. if (typeof user !== "undefined" && user !== null) {
    invite(user);
    }

    View Slide

  173. name = userName ? 'John'
    var name;
    name = typeof userName !== "undefined" && ↵
    userName !== null ? userName : 'John';

    View Slide

  174. name = 'John'
    name ?= 'Marcy'
    var name;
    name = 'John';
    if (name == null) {
    name = 'Marcy';
    }

    View Slide

  175. name = 'Marcy Murcy'
    john = name.match(/John/)?[0]
    var john, name, _ref;
    name = 'Marcy Murcy';
    john = (_ref = name.match(/John/)) != null ? ↵
    _ref[0] : void 0;

    View Slide

  176. console?.log? "foo"
    if (typeof console !== "undefined" && console !== null) {
    if (typeof console.log === "function") {
    console.log("foo");
    }
    }

    View Slide

  177. Loops and
    list comprehension

    View Slide

  178. Lists

    View Slide

  179. names = ['John', 'Marcy']
    for name in names
    invite(name)

    View Slide

  180. invite(name) for name in ['John', 'Marcy']

    View Slide

  181. var name, _i, _len, _ref;
    _ref = ['John', 'Marcy'];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    name = _ref[_i];
    invite(name);
    }

    View Slide

  182. invite(name, index) for name, index in ['John', 'Marcy']

    View Slide

  183. Conditional

    View Slide

  184. invite(n) for n in ['John', 'Marcy'] when n is 'John'

    View Slide

  185. Comprehension

    View Slide

  186. johns = (n for n in ['John', 'Marcy'] when n is 'John')

    View Slide

  187. var johns, n;
    johns = (function() {
    var _i, _len, _ref, _results;
    _ref = ['John', 'Marcy'];
    _results = [];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    n = _ref[_i];
    if (n === 'John') {
    _results.push(n);
    }
    }
    return _results;
    })();

    View Slide

  188. Steps

    View Slide

  189. evenNumbers = (n for n in [0..10] by 2)

    View Slide

  190. Objects

    View Slide

  191. users = john: 23, marcy: 29
    ageReport = for name, age of users
    "#{name} is #{age}"

    View Slide

  192. var age, ageReport, name, users;
    users = {
    john: 23,
    marcy: 29
    };
    ageReport = (function() {
    var _results;
    _results = [];
    for (name in users) {
    age = users[name];
    _results.push("" + name + " is " + age);
    }
    return _results;
    })();

    View Slide

  193. users = john: 23, marcy: 29
    ageReport = for own name, age of users
    "#{name} is #{age}"

    View Slide

  194. var age, ageReport, name, users,
    __hasProp = {}.hasOwnProperty;
    users = {
    john: 23,
    marcy: 29
    };
    ageReport = (function() {
    var _results;
    _results = [];
    for (name in users) {
    if (!__hasProp.call(users, name)) continue;
    age = users[name];
    _results.push("" + name + " is " + age);
    }
    return _results;
    })();

    View Slide

  195. while and until

    View Slide

  196. growUp(user) while user.age < 80
    growUp(user) until user.age >= 80

    View Slide

  197. loop -> poll()
    while (true) {
    (function() {
    return poll();
    });
    }

    View Slide

  198. Classes and inheritance

    View Slide

  199. class User

    View Slide

  200. var User;
    User = (function() {
    function User() {}
    return User;
    })();

    View Slide

  201. Constructor

    View Slide

  202. class User
    constructor: (name) ->
    @name = name

    View Slide

  203. var User;
    User = (function() {
    function User(name) {
    this.name = name;
    }
    return User;
    })();

    View Slide

  204. class User
    constructor: (@name) ->

    View Slide

  205. class User
    constructor: (@name = 'Undefined') ->

    View Slide

  206. Instance methods

    View Slide

  207. class User
    constructor: (@firstName, @lastName) ->
    fullName: ->
    "#{@firstName} #{@lastName}"
    john = new User('John', 'Doe')
    john.fullName()
    # => "John Doe"

    View Slide

  208. var User, john;
    User = (function() {
    function User(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    }
    User.prototype.fullName = function() {
    return "" + this.firstName + " " + this.lastName;
    };
    return User;
    })();

    View Slide

  209. Binding of this

    View Slide

  210. class View
    constructor: (@name)->
    $('a').on 'click', displayName
    displayName: =>
    $('h1').text @name

    View Slide

  211. Instance variables

    View Slide

  212. class User
    constructor: -> @invited = false

    View Slide

  213. Class methods
    (and variables)

    View Slide

  214. class User
    @_users: []
    @getUsers: -> User._users

    View Slide

  215. var User;
    User = (function() {
    function User() {}
    User._users = [];
    User.getUsers = function() {
    return User._users;
    };
    return User;
    })();

    View Slide

  216. Inheritance

    View Slide

  217. class User
    class Invitee extends User

    View Slide

  218. var Invitee, User, _ref,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if
    (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor()
    { this.constructor = child; } ctor.prototype = parent.prototype;
    child.prototype = new ctor(); child.__super__ = parent.prototype; return
    child; };
    User = (function() {
    function User() {}
    return User;
    })();
    Invitee = (function(_super) {
    __extends(Invitee, _super);
    function Invitee() {
    _ref = Invitee.__super__.constructor.apply(this, arguments);
    return _ref;
    }
    return Invitee;
    })(User);

    View Slide

  219. var Invitee, User, _ref,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if
    (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor()
    { this.constructor = child; } ctor.prototype = parent.prototype;
    child.prototype = new ctor(); child.__super__ = parent.prototype; return
    child; };
    User = (function() {
    function User() {}
    return User;
    })();
    Invitee = (function(_super) {
    __extends(Invitee, _super);
    function Invitee() {
    _ref = Invitee.__super__.constructor.apply(this, arguments);
    return _ref;
    }
    return Invitee;
    })(User);

    View Slide

  220. var Invitee, User, _ref,
    __hasProp = {}.hasOwnProperty,
    __extends = function (child, parent) {
    for (var key in parent) {
    if (__hasProp.call(parent, key)) {
    child[key] = parent[key];
    }
    }
    function ctor() {
    this.constructor = child;
    }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor();
    child.__super__ = parent.prototype;
    return child;
    };

    View Slide

  221. User = (function() {
    function User() {}
    return User;
    })();

    View Slide

  222. Invitee = (function(_super) {
    __extends(Invitee, _super);
    function Invitee() {
    _ref = Invitee.__super__.constructor.apply(this, ↵
    arguments);
    return _ref;
    }
    return Invitee;
    })(User);

    View Slide

  223. Super

    View Slide

  224. class User
    constructor: (@name) ->
    message: -> "Hello #{@name}!"
    class Invitee extends User
    message: ->
    "#{super()} You are invited"
    invitee = new Invitee 'John'
    invitee.message()
    # => "Hello John! You are invited"

    View Slide

  225. Invitee.prototype.message = function() {
    return "" + (Invitee.__super__.message.call(this)) ↵
    + " You are invited";
    };

    View Slide

  226. Direct prototype access

    View Slide

  227. String::dasherize = ->
    this.replace /_/g, "-"
    String.prototype.dasherize = function() {
    return this.replace(/_/g, "-");
    };

    View Slide

  228. Summary

    View Slide

  229. CoffeeScript makes
    Javascript fun again

    View Slide

  230. Common complaints

    View Slide

  231. Teamwork

    View Slide

  232. Debugging

    View Slide

  233. WORKSHOP!

    View Slide