Slide 1

Slide 1 text

How CoffeeScript deprecates JavaScript

Slide 2

Slide 2 text

A bit of history

Slide 3

Slide 3 text

A bit of history from 1995

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

1995 Brendan Eich CTO Mozilla Foundation

Slide 8

Slide 8 text

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.

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

1995 Javascript: The Good Parts Javascript: The Definitive Guide

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

XMLHttpRequest 2000 Internet Explorer 5.0

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

2004

Slide 18

Slide 18 text

2005

Slide 19

Slide 19 text

2005

Slide 20

Slide 20 text

2005 Sam Stephenson 37signals

Slide 21

Slide 21 text

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); }

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

2006 John Resig Khan Academy

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

So, basically, we’re trapped x

Slide 29

Slide 29 text

unless. x

Slide 30

Slide 30 text

We start thinking about Javascript more like bytecode %

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

@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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

2009 Jeremy Ashkenas DocumentCloud

Slide 36

Slide 36 text

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.

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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; } };

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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);

Slide 44

Slide 44 text

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!

Slide 45

Slide 45 text

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()

Slide 46

Slide 46 text

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!

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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(", ") }"

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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 });

Slide 52

Slide 52 text

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!

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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 """

Slide 55

Slide 55 text

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)

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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!"

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

Thanks! @steffoz U stefanoverna.com Y