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

How CoffeeScript deprecates Javascript

How CoffeeScript deprecates Javascript

Stefano Verna

May 22, 2012
Tweet

More Decks by Stefano Verna

Other Decks in Programming

Transcript

  1. How CoffeeScript deprecates JavaScript

    View Slide

  2. A bit of history

    View Slide

  3. A bit of history
    from 1995

    View Slide

  4. View Slide

  5. 1995
    Netscape Navigator 2.0
    vs. IE 1.0 (Microsoft Windows 95 Plus! Pack)

    View Slide

  6. 1995
    Netscape wanted a lightweight
    interpreted language that would
    complement Java by appealing to
    nonprofessional programmers,
    like Microsoft's Visual Basic.

    View Slide

  7. 1995
    Brendan Eich
    CTO Mozilla Foundation

    View Slide

  8. 1995
    JS had to “look like
    Java”, only less so. It
    had to be Java’s dumb
    kid brother or boy-
    hostage sidekick.
    Plus, it had to be done
    in ten days.

    View Slide

  9. 1995
    Not a bad language, for a 10 days effort.
    % Prototypal inheritance
    % First-class functions
    % First-class closures
    % Object and Array literals
    % Loose typing

    View Slide

  10. 1995
    Not a great language, neither.
    × Ugly, verbose syntax
    × Dependency on globals
    × No block scopes
    × Equality coersion
    × A lot more

    View Slide

  11. 1995
    Javascript:
    The Good Parts
    Javascript:
    The Definitive Guide

    View Slide

  12. 1995
    For 5 long years, it’s just news ticker
    and countdown timers.
    2000

    View Slide

  13. 1995
    For 5 long years, it’s just news ticker
    and countdown timers.
    2000

    View Slide

  14. XMLHttpRequest
    2000
    Internet Explorer 5.0

    View Slide

  15. No one gives a fuck.
    2000
    AJAX days still have to come.

    View Slide

  16. 2004
    Until 2004.
    (AJAX finally implemented on most browsers.)

    View Slide

  17. 2004

    View Slide

  18. 2005

    View Slide

  19. 2005

    View Slide

  20. 2005
    Sam Stephenson
    37signals

    View Slide

  21. var names = [];
    for (var i = 0, l = people.length; i < l; i++) {
    var person = people[i];
    var name =
    person.name.slice(0, 1).toUpperCase() +
    person.name.slice(1);
    names.push(name);
    }

    View Slide

  22. names = people.map do |person|
    person.name.capitalize
    end

    View Slide

  23. names = people.map do |person|
    person.name.capitalize
    end
    var names = people.map(
    function (person) {
    return person.name.capitalize();
    }
    );

    View Slide

  24. Beautiful, readable, ruby-ish syntax
    High use of monkey-patching
    Namespace clashing

    View Slide

  25. Beautiful, readable, ruby-ish syntax
    High use of monkey-patching
    Namespace clashing

    View Slide

  26. 2006
    John Resig
    Khan Academy

    View Slide

  27. var names = $.each(people, function(person) {
    return capitalize(person.name);
    }
    );
    jQuery.noConflict()
    A broader audience, a safer approach
    A step backward in readability

    View Slide

  28. So, basically, we’re trapped
    x

    View Slide

  29. unless.
    x

    View Slide

  30. We start thinking about Javascript
    more like bytecode
    %

    View Slide

  31. View Slide

  32. A desktop-like development experience
    There’s no HTML, CSS or JS
    No direct interaction with the browser
    Java ObjC Python
    2008

    View Slide

  33. @implementation AppController : CPObject { }
    - (void)applicationDidFinishLaunching:(CPNotification)note
    {
    theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero()
    styleMask:CPBorderlessBridgeWindowMask];
    contentView = [theWindow contentView];
    var label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
    [label setStringValue:@"Hello World!"];
    [label setFont:[CPFont boldSystemFontOfSize:24.0]];
    [label sizeToFit];
    [label setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin];
    [label setFrameOrigin:CGRectMake(100,100)];
    [contentView addSubview:label];
    [theWindow orderFront:self];
    }
    @end

    View Slide

  34. But I like the web!
    I just want the bad parts fixed!
    (

    View Slide

  35. 2009
    Jeremy Ashkenas
    DocumentCloud

    View Slide

  36. 2009
    Underneath all those awkward braces and
    semicolons, JavaScript has always had a
    gorgeous object model at its heart.
    CoffeeScript is an attempt to expose the good
    parts of JavaScript in a simple way.
    The golden rule of CoffeeScript is: "It's just
    JavaScript". CoffeeScript generates clean
    and readable JavaScript.

    View Slide

  37. (function() {
    /* your program here */
    }).call(this);
    Private by default (self-executing function)
    # Your program here

    View Slide

  38. function greet (name) {
    return "Hello " + name;
    }
    Function syntax & automatic return
    greet = (name) ->
    "Hello " + name

    View Slide

  39. function greet (name) {
    return "Hello " + name;
    }
    Function syntax & automatic return
    greet = (name) ->
    "Hello " + name
    Approved feature in
    ECMAScript.next
    http://goo.gl/JsXQ5

    View Slide

  40. greet = (name) ->
    if name == "@tenderlove"
    "ZOMG! HI " + name + "!!!"
    else
    "Hello " + name
    Everything is an expression
    var greet = function(name) {
    if (name === "@tenderlove") {
    return "ZOMG! HI " + name + "!!!";
    } else {
    return "Hello " + name;
    }
    };

    View Slide

  41. var names, person;
    names = (function() {
    var _i, _len, _results;
    _results = [];
    for (_i = 0, _len = people.length; _i < _len; _i++) {
    person = people[_i];
    _results.push(capitalize(person.name));
    }
    return _results;
    })();
    names = for person in people
    capitalize person.name
    Everything is an expression /2

    View Slide

  42. "ZOMG! HI #{ name }!!!"
    Ruby-style string interpolation
    "ZOMG! HI " + name + "!!!";

    View Slide

  43. foo = false
    bar = "0"
    console.log foo == bar # -> false
    console.log foo != bar # -> true
    Strict comparisons (no more equality coertion)
    var bar, foo;
    foo = false;
    bar = "0";
    console.log(foo === bar);
    console.log(foo !== bar);

    View Slide

  44. foo = false
    bar = "0"
    console.log foo == bar # -> false
    console.log foo != bar # -> true
    Strict comparisons (no more equality coertion)
    var bar, foo;
    foo = false;
    bar = "0";
    console.log(foo === bar);
    console.log(foo !== bar);
    In JS, if you use ==
    you’ll get the exactly
    opposite result!

    View Slide

  45. var changeNumbers, inner, outer;
    outer = 1;
    changeNumbers = function() {
    var inner;
    inner = -1;
    return outer = 10;
    };
    inner = changeNumbers();
    No more var (Ruby-like scoping)
    outer = 1
    changeNumbers = ->
    inner = -1
    outer = 10
    inner = changeNumbers()

    View Slide

  46. var changeNumbers, inner, outer;
    outer = 1;
    changeNumbers = function() {
    var inner;
    inner = -1;
    return outer = 10;
    };
    inner = changeNumbers();
    No more var (Ruby-like scoping)
    outer = 1
    changeNumbers = ->
    inner = -1
    outer = 10
    inner = changeNumbers()
    In JS, you omit “var”
    you’re leaking variables
    on the outer scope!

    View Slide

  47. var languageOfChoice = function(lang) {
    if (lang == null) {
    lang = "Ruby";
    }
    return "" + lang + " rocks!";
    };
    Parameter default values
    languageOfChoice = (lang = "Ruby") ->
    "#{ lang } rocks!"

    View Slide

  48. var languageOfChoice = function(lang) {
    if (lang == null) {
    lang = "Ruby";
    }
    return "" + lang + " rocks!";
    };
    Parameter default values
    languageOfChoice = (lang = "Ruby") ->
    "#{ lang } rocks!"
    Approved feature in
    ECMAScript.next
    http://goo.gl/JsXQ5

    View Slide

  49. var __slice = [].slice;
    var languagesOfChoice = function() {
    var best, others;
    best = arguments[0], others = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
    return "I love " + best + ", but I like also " + (others.join(", "));
    };
    Arguments splat
    languagesOfChoice = (best, others...) ->
    "I love #{ best }, but I like also #{ others.join(", ") }"

    View Slide

  50. var __slice = [].slice;
    var languagesOfChoice = function() {
    var best, others;
    best = arguments[0], others = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
    return "I love " + best + ", but I like also " + (others.join(", "));
    };
    Arguments splat
    languagesOfChoice = (best, others...) ->
    "I love #{ best }, but I like also #{ others.join(", ") }"
    Approved feature in
    ECMAScript.next
    http://goo.gl/JsXQ5

    View Slide

  51. console.log [ 1, 2, 3, ]
    console.log { foo: 1, bar: 2, }
    JSLint validatable code (runs everywhere)
    console.log([1, 2, 3]);
    console.log({
    foo: 1,
    bar: 2
    });

    View Slide

  52. console.log [ 1, 2, 3, ]
    console.log { foo: 1, bar: 2, }
    JSLint validatable code (runs everywhere)
    console.log([1, 2, 3]);
    console.log({
    foo: 1,
    bar: 2
    });
    IE would have thrown
    a compilation error on
    this one!

    View Slide

  53. return if elements.length == 0
    launch() if ignition is on
    volume = 10 if band isnt SpinalTap
    letTheWildRumpusBegin() unless answer is no
    if car.speed < limit then accelerate()
    winner = yes if pick in [47, 92, 13]
    Statement Modifiers & Operator aliases

    View Slide

  54. Multiline strings
    var mobyDick = "Call me Ishmael. Some years ago -- never mind how long
    precisely -- having little or no money in my purse, and nothing
    particular to interest me on shore, I thought I would sail about a
    little and see the watery part of the world...";
    var html = "\n cup of coffeescript\n";
    mobyDick = "Call me Ishmael. Some years ago --
    never mind how long precisely -- having little
    or no money in my purse, and nothing particular
    to interest me on shore, I thought I would sail
    about a little and see the watery part of the
    world..."
    html = """

    cup of coffeescript

    """

    View Slide

  55. class Animal
    constructor: (@name) ->
    move: (meters) ->
    alert @name + " moved #{meters}m."
    dog = new Animal("Fido")
    var Animal = (function() {
    function Animal(name) {
    this.name = name;
    }
    Animal.prototype.move = function(meters) {
    return alert(this.name + (" moved " + meters + "m."));
    };
    return Animal;
    })();
    Built-in classical OOP (the @ alias)

    View Slide

  56. var Animal, Snake,
    __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; };
    Snake = (function(_super) {
    __extends(Snake, _super);
    function Snake() {
    return Snake.__super__.constructor.apply(this, arguments);
    }
    Snake.prototype.move = function() {
    alert("Slithering...");
    return Snake.__super__.move.call(this, 5);
    };
    return Snake;
    })(Animal);
    Inheritance
    class Snake extends Animal
    move: ->
    alert "Slithering..."
    super 5

    View Slide

  57. Bound functions (fat arrow)
    class @View
    constructor: (@name) ->
    @el = $("").appendTo("body")
    @attachEvents()
    attachEvents: ->
    @el.click ->
    alert "#{@name} view!"

    View Slide

  58. class @View
    constructor: (@name) ->
    @el = $("").appendTo("body")
    @attachEvents()
    attachEvents: ->
    this.el.click(
    function() { alert(_this.name + " view"); }
    );
    Bound functions (fat arrow)

    View Slide

  59. class @View
    constructor: (@name) ->
    @el = $("").appendTo("body")
    @attachEvents()
    attachEvents: ->
    var _this = this;
    this.el.click(
    function() { alert(_this.name + " view"); }
    );
    Bound functions (fat arrow)

    View Slide

  60. Bound functions (fat arrow)
    class @View
    constructor: (@name) ->
    @el = $("").appendTo("body")
    @attachEvents()
    attachEvents: ->
    @el.click =>
    alert "#{@name} view!"

    View Slide

  61. Bound functions (fat arrow)
    Approved feature in
    ECMAScript.next
    http://goo.gl/JsXQ5
    class @View
    constructor: (@name) ->
    @el = $("").appendTo("body")
    @attachEvents()
    attachEvents: ->
    @el.click =>
    alert "#{@name} view!"

    View Slide

  62. Closure wrappers
    var number = 10;
    function check() {
    return number;
    };
    number = 20;
    check();

    View Slide

  63. Closure wrappers
    var number = 10;
    function check() {
    return number;
    };
    number = 20;
    check(); // 20

    View Slide

  64. Closure wrappers
    for (var i = 0; i < 5; i++) {
    $("")
    .text(i)
    .appendTo("body")
    .click(function() {
    alert("Clicked " + i);
    });
    }

    View Slide

  65. Closure wrappers
    for (var i=0; i<5; i++) {
    (function(i) {
    $("")
    .text(i)
    .appendTo("body")
    .click(function() {
    alert("Clicked " + i);
    });
    })(i);
    }

    View Slide

  66. Closure wrappers
    for i in [0...5]
    do (i) ->
    $("")
    .appendTo("body")
    .text(i)
    .click ->
    alert("Clicked #{i}")

    View Slide

  67. Everything else you might miss from Ruby.
    • Array slicing
    • Destructured assignments
    • Block regular expressions
    • Optional parenthesis
    • Existential operators

    View Slide

  68. Thanks!
    @steffoz
    U
    stefanoverna.com
    Y

    View Slide