Share
Embed
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
FOWA 2011
Sam Stephenson
October 05, 2011
Transcript
110 slides
-
CoffeeScript is Beautiful & I Never Want to Write Plain
JavaScript Again -
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); } -
package com.example.gwt.helloworld.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; public class HelloWorld implements EntryPoint { @Override public void onModuleLoad() { Label label = new Label("Hello world"); Button button = new Button("Say something"); button.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.alert("Hello again"); } }); RootPanel.get().add(label); RootPanel.get().add(button); } } -
<?xml version="1.0" encoding="UTF-8"?> <module rename-to='com_example_gwt_helloworld'> <!-- Inherit the core Web
Toolkit stuff. --> <inherits name='com.google.gwt.user.User'/> <inherits name='com.google.gwt.user.theme.standard.Standard'/> <!-- Specify the app entry point class. --> <entry-point class='com.example.gwt.helloworld.client.HelloWorld'/> </module> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <!-- Default page to serve --> <welcome-file-list> <welcome-file>Com_example_gwt_helloworld.html</welcome-file> </welcome-file-list> </web-app> -
function hello(){var l='',F='" for "gwt:onLoadErrorFn"',D='" for "gwt:onPropert yErrorFn"',n='"><\/script>',p='#',r='/',vb='02EDD05CEF7D978C649BF91CC66AB635.ca che.html',sb='28600060343BDDEB1FD83487846D090C.cache.html',ub='9EDF9C067C3A475F 6EA7A16003CA4979.cache.html',Fb='<script
defer="defer">hello.onInjectionDone(\' hello\')<\/script>',dc='<script id="',A='=',q='?',C='Bad handler "',tb='D69BADE 681FFFC6071DFA4FC25EF1DC5.cache.html',Eb='DOMContentLoaded',wb='F26BFE33DA14C23 176C7BC08D58AA43F.cache.html',o='SCRIPT',cc='__gwt_marker_hello',s='base',nb='b egin',cb='bootstrap',u='clear.cache.gif',z='content',bc='end',lb='gecko',mb='ge cko1_8',yb='gwt.hybrid',xb='gwt/standard/standard.css',E='gwt:onLoadErrorFn',B= 'gwt:onPropertyErrorFn',y='gwt:property',Db='head',qb='hosted.html?hello',Cb='h ref',kb='ie6',ab='iframe',t='img',bb="javascript:''",zb='link',pb='loadExternal Refs',v='meta',eb='moduleRequested',ac='moduleStartup',jb='msie',w='name',gb='o pera',db='position:absolute;width:0;height:0;border:none',Ab='rel',ib='safari', rb='selectingPermutation',x='startup',m='hello',Bb='stylesheet',ob='unknown',fb ='user.agent',hb='webkit';var fc=window,k=document,ec=fc.__gwtStatsEvent?functi on(a){return fc.__gwtStatsEvent(a)}:null,zc,pc,kc,jc=l,sc={},Cc=[],yc=[],ic=[], vc,xc;ec&&ec({moduleName:m,subSystem:x,evtGroup:cb,millis:(new Date()).getTime( ),type:nb});if(!fc.__gwt_stylesLoaded){fc.__gwt_stylesLoaded={}}if(!fc.__gwt_sc riptsLoaded){fc.__gwt_scriptsLoaded={}}function oc(){var b=false;try{b=fc.exter nal&&(fc.external.gwtOnLoad&&fc.location.search.indexOf(yb)==-1)}catch(a){}oc=f unction(){return b};return b}function rc(){if(zc&&pc){var c=k.getElementById(m) ;var b=c.contentWindow;if(oc()){b.__gwt_getProperty=function(a){return lc(a)}}h ello=null;b.gwtOnLoad(vc,m,jc);ec&&ec({moduleName:m,subSystem:x,evtGroup:ac,mil lis:(new Date()).getTime(),type:bc})}};function mc(){var j,h=cc,i;k.write(dc+h+ n);i=k.getElementById(h);j=i&&i.previousSibling;while(j&&j.tagName!=o){j=j.prev iousSibling}function f(b){var a=b.lastIndexOf(p);if(a==-1){a=b.length}var c=b.i ndexOf(q);if(c==-1){c=b.length}var d=b.lastIndexOf(r,Math.min(c,a));return d>=0 ?b.substring(0,d+1):l};if(j&&j.src){jc=f(j.src)}if(jc==l){var e=k.getElementsBy TagName(s);if(e.length>0){jc=e[e.length-1].href}else{jc=f(k.location.href)}}els e if(jc.match(/^\w+:\/\//)){}else{var g=k.createElement(t);g.src=jc+u;jc=f(g.sr -
import pyjd # this is dummy in pyjs. from pyjamas.ui.RootPanel
import RootPanel from pyjamas.ui.Button import Button from pyjamas.ui.HTML import HTML from pyjamas.ui.Label import Label from pyjamas import Window import pygwt def greet(fred): fred.setText("No, really click me!") Window.alert("Hello, AJAX!") if __name__ == '__main__': pyjd.setup("public/Hello.html?fred=foo#me") b = Button("Click me", greet, StyleName='teststyle') h = HTML("<b>Hello World</b> (html)", StyleName='teststyle') l = Label("Hello World (label)", StyleName='teststyle') base = HTML("Hello from %s" % pygwt.getModuleBaseURL(), StyleName='teststyle') RootPanel().add(b) RootPanel().add(h) RootPanel().add(l) RootPanel().add(base) pyjd.run() -
I love/prefer {insert AJAX / Javascript framework here}, how do
I use it? Not being funny or anything, but unless you have the resources of google or lots of money or lots of time, or you can gather enough people to make it so that everyone has less work to do: you don't. huh? why?? Some of the widgets in DojoX / Ext-JS are really cute! I want them! waaah! You are not in Kansas any more. Pyjamas is declarative- style programming, using a "real" programming language. All those widget-sets were designed to be driven from inside HTML (a style of web development which, using Pyjamas, you have just left far behind) and by inserting javascript snippets into the HTML. If you try that with a Pyjamas app, you are not only likely to get yourself into an -
I love/prefer {insert AJAX / Javascript framework here}, how do
I use it? Not being funny or anything, but unless you have the resources of google or lots of money or lots of time, or you can gather enough people to make it so that everyone has less work to do: you don't. huh? why?? Some of the widgets in DojoX / Ext-JS are really cute! I want them! waaah! You are not in Kansas any more. Pyjamas is declarative- style programming, using a "real" programming language. All those widget-sets were designed to be driven from inside HTML (a style of web development which, using Pyjamas, you have just left far behind) and by inserting javascript snippets into the HTML. If you try that with a Pyjamas app, you are not only likely to get yourself into an -
I love/prefer {insert AJAX / Javascript framework here}, how do
I use it? Not being funny or anything, but unless you have the resources of google or lots of money or lots of time, or you can gather enough people to make it so that everyone has less work to do: you don't. huh? why?? Some of the widgets in DojoX / Ext-JS are really cute! I want them! waaah! You are not in Kansas any more. Pyjamas is declarative- style programming, using a "real" programming language. All those widget-sets were designed to be driven from inside HTML (a style of web development which, using Pyjamas, you have just left far behind) and by inserting javascript snippets into the HTML. If you try that with a Pyjamas app, you are not only likely to get yourself into an -
@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 -
CoffeeScript is a little language that compiles into JavaScript. Underneath
all of those embarrassing 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”. The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. -
CoffeeScript is a little language that compiles into JavaScript. Underneath
all of those embarrassing 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”. The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. -
CoffeeScript is a little language that compiles into JavaScript. Underneath
all of those embarrassing 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”. The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. -
Good Part: Private by default (function() { /* your program
here */ }).call(this); -
Good Part: No more var lastClick = 0 $("a").click ->
now = new Date().getTime() if now - lastClick > 100 $("#message").show() lastClick = now -
Good Part: No more var var lastClick = 0 $("a").click
-> var now = new Date().getTime() if now - lastClick > 100 $("#message").show() lastClick = now -
Good Part: Strict comparisons "true" == true // true "true"
=== true // false "0" == false // true "0" == 0 // true 0 === false // false "" == false // true -
Good Part: Strict comparisons "true" is true // false "true"
is "true" // true "0" is false // false "0" is 0 // false 0 is 0 // true "" is false // false -
2. Significant Whitespace if (url) { $.get(url, function(data) { return
$("#result").html(data); }); } else { $("#error").show(); } -
2. Significant Whitespace if url $.get url, (data) -> $("#result").html
data else $("#error").show() -
2. Significant Whitespace var readConfiguration = function(callback) { return path.exists(filename,
function(err, exists) { if (exists) { return fs.readFile(filename, callback); } else { return callback(false); } }); }; -
2. Significant Whitespace readConfiguration = (callback) -> path.exists filename, (err,
exists) -> if exists fs.readFile filename, callback else callback false -
3. Bare Objects $.ajax({ url: path, timeout: 5, data: {
from: "workspace" }, dataType: "html", success: function(data) { return $("#result").html(data); } }); -
3. Bare Objects $.ajax url: path, timeout: 5, data: from:
"workspace", dataType: "html", success: (data) -> $("#result").html data -
4. Everything’s an Expression switch keyCode when 38 command =
"previous" when 40 command = "next" when 13 command = "select" -
4. Everything’s an Expression command = switch keyCode when 38
then "previous" when 40 then "next" when 13 then "select" -
4. Everything’s an Expression getCommand = (keyCode) -> switch keyCode
when 38 then "previous" when 40 then "next" when 13 then "select" -
5. Comprehensions names = [] for person in people names.push
capitalize person.name -
5. Comprehensions names = for person in people when age
> 27 capitalize person.name -
5. Comprehensions var names, person; names = (function() { var
_i, _len, _results; _results = []; for (_i = 0, _len = people.length; _i < _len; _i++) { person = people[_i]; if (age > 27) { _results.push(capitalize(person.name)); } } return _results; })(); -
6. Classes & Inheritance class Photo constructor: (url) -> this.url
= url createElement: -> $("<img>").attr "src", this.url -
6. Classes & Inheritance class Photo constructor: (url) -> this.url
= url createElement: -> $("<img>").attr "src", this.url -
6. Classes & Inheritance class Photo constructor: (url) -> @url
= url createElement: -> $("<img>").attr "src", @url -
6. Classes & Inheritance class Photo constructor: (@url) -> createElement:
-> $("<img>").attr "src", @url -
6. Classes & Inheritance class Thumbnail extends Photo createElement: ->
$el = super $el.height 100 -
6. Classes & Inheritance var Thumbnail; var __hasProp = Object.prototype.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; }; Thumbnail = (function() { __extends(Thumbnail, Photo); function Thumbnail() { Thumbnail.__super__.constructor.apply(this, arguments); } Thumbnail.prototype.createElement = function() { var $el; $el = Thumbnail.__super__.createElement.apply(this, arguments); return $el.height(100); }; return Thumbnail; })(); -
7. Bound Functions class PersonView constructor: (@person, @el) -> request:
-> $.get @person.url, (data) -> $(@el).html data -
7. Bound Functions class PersonView constructor: (@person, @el) -> request:
-> $.get @person.url, (data) -> $(@el).html data -
7. Bound Functions function request () { $.get(this.person.url, (function(data) {
$(this.el).html(data); }).bind(this) ) } -
7. Bound Functions class PersonView constructor: (@person, @el) -> request:
-> $.get @person.url, (data) => $(@el).html data -
7. Bound Functions class PersonView constructor: (@person, @el) -> $(@el).bind
"click", @showName showName: => $(@el).html @person.name -
10. String Syntax render = (person) -> """ <div class="person">
<a href="#{person.url}">#{person.name}</a> <span>#{person.profession}</span> </div> """ -
Command Line $ coffee -c hello.coffee $ cat hello.js (function()
{ alert("hello"); }).call(this);