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. 1995 Netscape wanted a lightweight interpreted language that would complement

    Java by appealing to nonprofessional programmers, like Microsoft's Visual Basic.
  2. 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.
  3. 1995 Not a bad language, for a 10 days effort.

    % Prototypal inheritance % First-class functions % First-class closures % Object and Array literals % Loose typing
  4. 1995 Not a great language, neither. × Ugly, verbose syntax

    × Dependency on globals × No block scopes × Equality coersion × A lot more
  5. 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); }
  6. names = people.map do |person| person.name.capitalize end var names =

    people.map( function (person) { return person.name.capitalize(); } );
  7. var names = $.each(people, function(person) { return capitalize(person.name); } );

    jQuery.noConflict() A broader audience, a safer approach A step backward in readability
  8. A desktop-like development experience There’s no HTML, CSS or JS

    No direct interaction with the browser Java ObjC Python 2008
  9. @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
  10. 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.
  11. (function() { /* your program here */ }).call(this); Private by

    default (self-executing function) # Your program here
  12. function greet (name) { return "Hello " + name; }

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

    Function syntax & automatic return greet = (name) -> "Hello " + name Approved feature in ECMAScript.next http://goo.gl/JsXQ5
  14. 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; } };
  15. 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
  16. 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);
  17. 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!
  18. 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()
  19. 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!
  20. var languageOfChoice = function(lang) { if (lang == null) {

    lang = "Ruby"; } return "" + lang + " rocks!"; }; Parameter default values languageOfChoice = (lang = "Ruby") -> "#{ lang } rocks!"
  21. 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
  22. 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(", ") }"
  23. 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
  24. 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 });
  25. 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!
  26. 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
  27. 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 = "<strong>\n cup of coffeescript\n</strong>"; 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 = """ <strong> cup of coffeescript </strong> """
  28. 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)
  29. 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
  30. Bound functions (fat arrow) class @View constructor: (@name) -> @el

    = $("<div/>").appendTo("body") @attachEvents() attachEvents: -> @el.click -> alert "#{@name} view!"
  31. class @View constructor: (@name) -> @el = $("<div/>").appendTo("body") @attachEvents() attachEvents:

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

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

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

    @View constructor: (@name) -> @el = $("<div/>").appendTo("body") @attachEvents() attachEvents: -> @el.click => alert "#{@name} view!"
  35. Closure wrappers var number = 10; function check() { return

    number; }; number = 20; check(); // 20
  36. Closure wrappers for (var i = 0; i < 5;

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

    $("<div/>") .text(i) .appendTo("body") .click(function() { alert("Clicked " + i); }); })(i); }
  38. Closure wrappers for i in [0...5] do (i) -> $("<div/>")

    .appendTo("body") .text(i) .click -> alert("Clicked #{i}")
  39. Everything else you might miss from Ruby. • Array slicing

    • Destructured assignments • Block regular expressions • Optional parenthesis • Existential operators