npm install -g coffee-script
@timglabisch
bei fragen - fragen! ;)
wer nutzt
- CoffeeScript?
- JavaScript?
- "oop"?
... compile to JavaScript ...?
- Am Anfang die gewohnte Frage, ....
- Wer nutzt CoffeeScript?
- wer könnte sich vorstellen morgen CoffeeScript zu nutzen?
- Wer nutzt Javascript?
- Wer scheibt oop Javascript?
- Wer nutzt Gwt, Dart, Typescript, ...
Coffeescript Basic's
syntax und so.
- Wer will eine langweilige Wikipedia-Einführung in Coffeescript hören?
- Ich übersetze die folgenden Statements in Coffeescript
- Im Anschluss erzähl ich vielleicht ein wenig Historie :)
-
Editor:
- output unten
- erkennt ob javascript
- wenn coffeescript, javascript rechts daneben
- valides Javascript
- \u1000 und က bedeuten identisches
- Kein Semikolion
-
Kein var Statement
- Coffeescript hat einen scope aware parser, anders als php, c, js, ...
- Coffeescript erkennt, dass var noch nicht deklariert ist
- Kein Mix aus Utf8 Zeichen, aus \u1000 -> က
- Unterstes က entfernen, return value stimmt noch!
- var davor schreiben, return value stimmt nicht mehr
- alles ist eine Expression, alles gibt was zurück, alles!
-
Resultat:
if(0 === -0) {
var a = 1;
}
a
- 1. Übersetzen in Coffeescript
- 2. was ist unnötig?
- 1. Semikolon
- 2. Klammern { und }
- --- HEY wir haben Javascript!
- 3. var
- 4. Klammern ( und )
- 5. doppelte gleichheitszeichen
- 1. Coffeescript kennt keine schwachen vergleichsoperatoren
- 2. a = 1 if `0 == -0` geht
- 3. optional "is" möglich
-
if 0 == -0
a = 1
-
Oder:
a = 1 if 0 is -0
-
Oder:
0 is -0 && a = 1
-
&& entspricht and
-
ACHTUNG
- if Statement gibt was zurück!
- bei coffeescript gibt alles etwas zurück :)
THERE IS NO FUCKING MAGIC, REALLY
THERE(IS(NO(FUCKING(MAGIC, REALLY))))
THERE IS ( NO (
FUCKING MAGIC, REALLY)
)
- 1. Funktionsaufrufe durch leerzeichen getrennt
- 2. Syntax ist wenig überraschend
-
3. Syntax lässt sich mischen, klammern sind optional
- 1. Klammern müssen gesetzt werden wenns ohne doppeldeutig wäre
- 4. Syntax ist sehr gnädig (letztes Beispiel)
-
5. Warum alles groß geschrieben?
(function() {
return 5;
})()
- 1. Semikolon entfernen
- 2. klammern weg
- 3. function durch ->
- 4. klammern hinzufügen, self call ...
- 5. return weg
- (-> 5)()
a = ->->->->->5
a()()()()()
console.log "up" if console?.log
- Existence operatoren
- oder einfach nur console?.log?
- oder einfach nur console?.log "up"
- schick schick für callbacks
x('._foo').html """
a href="#{getRouter().url 'user', user.id}">
img src="#{getUserImageService().getImage(user).getSrc()}"/>
/a>
"""
- 1. < am Anfang com HTML ricgtig setzen
- 2. mehrere Zeilen
- 3. Funktionen lassen sich embedden
- Zuweisung falls kein wert vorhanden
function add(a, b) {
return a + b;
}
add("Why am I a ", typeof + "");
- Etwas komplizierteres beispiel
- - was entfernen damit Syntaktisch noch korrekt?
- - ;
- - return
- - function
- - {
- - (
- + =
- + ->
-
- add = (a, b) -> a + b;
-
- add "Why am I a ", typeof + ""
-
- warum ists ne nummer?
-
+"" ist ne nummer :)
(typeof(+""))
$(document).ready(function() {
$("body").removeClass("noscript")
});
- Coffeescript wird 1 zu 1 zu Javascript.
- Ihr könnt jederzeit das Coffeescript verwerfen.
-
- Keine komplexen Proxies wie z.b. bei Dart / GWT nötig
-
Skript stimmt von trivago
-
jegliches Warum bitte an die frontend devs ...
The golden rule of CoffeeScript is:
"It's just JavaScript".
- 1. wer Javascript kann, lernt CoffeeScript sehr schnell
- 2. nur anderer Syntax
- 2. maximal kompaktibel
The compiled output is readable and pretty-printed, ...
- Ich mag keine Überraschungen
- 1. CoffeeScript generiert was du erwartest, keine Überraschungen
- 2. der Output ist lesbar, debugbar
-
3. solltest du weg wollen von CoffeeScript, schnapp dir das JS...
- 3.1 Der Weg zurück wird nie verbaut
- 3.2 Anders als bei z.b. GWT
will work in every JavaScript runtime, ...
- Ecmascript 5?
- IE 6 ist kein Problem
- kein problem auch optimiertes js zu embedden - solltet ihr was schnelleres finden ... :)
... and tends to run as fast or faster than the equivalent handwritten JavaScript.
-
Kein ASM.js
-
Glaubensfrage.
-
1. Optimiert nicht auf den Browser
-
2. wollt ihr z.b. forEach, map o. etc. nutzen, tut es.
ASM.js for speed
GWT for nerds working @google
Dart for hipsters
JavaScript for runtime
CoffeeScript for humans (and PHP dev's :))
-
JS ist hölle für jede Runtime, nur google hat interesse dran ...
var someInt = 4;
add = function(x, y) {
return x + y;
}
add(someInt, add(someInt, 5));
- just translate
- kaskadierte funktion
- auf die klammern achten
greeter = (name) ->
"hello " + name
x = (cb, arr) ->
cb name for name in arr
x(greeter, ["Andy", "Mario", "..."]).join ', '
- 1. Code sieht komisch aus?
- 2. Return Statement hinzufügen!
- 3. wo ist der unterschied?
-
4. letztes Statement wird returnt!
- for hat eine return value!
- ein array!
- 5. wir sammeln alle rückgabewerte des Callbacks!
names = -> name for name in ["Andy", 'Maro', '...']
names().join ', '
- Beispiel return Value der Collection von names.
$('meta')
.toArray()
.map((el) -> $(el).attr 'name')
.filter((x) -> x && x.length)
.reduce((a, b) -> a + ', ' + b)
- Einfaches map and reduce Beispiel
- underscore js ist auch von jeremy
- funktional geht natürlich immer :)
$('some_selector').css({top: 42, left: 42})
- Objektsyntax
- .css top: 42, left: 42
- oder
-
.css
- korrigiert jegliche komma's
$.ajax
url: url
timeout: 5
data:
form: "workspace"
dataType: "jsonp"
success: (data) =>
@setXData data
- Wenn ihr es in { und } schreibt, dann geht auf "url" anstelle von url: url
x = (keyCode) ->
switch keyCode
when 38
command = "previous"
when 40
command = "next"
return command if command
x 38
- Switch hat einen Rückgabewert
x = (keyCode) ->
switch keyCode
when 38 then "previous"
when 40 then "next"
x 38
- alternative Schreibweise um mit Switch zu arbeiten
CoffeeScript in the wild
- ich hatte im vorfeld mal gefragt
- 1. Praxisnahe Beispiele sollten es sein :)
- wie man unten sieht, valides CoffeeScript
- Eklig sowas,
- Singleton, keine Architektur
- - Just works -
- nicht wartbar?
- Wir sind Architekten :)
var a = (function() {
function a() {}
a.prototype.foo = function() {
return "bar";
};
return a;
})();
(new a).foo()
- wer scheibt sowas in JavaScript?
a bit oop
- wer schreibt oop JavaScript?
- warum nicht?
- oop ist performant!
class a
foo: -> "bar"
(new a).foo()
- CoffeeScript kann klassen
- Class.create war der grund für prototypeJS
-
wer findet rechts übersichtlicher?
-
wer von denen will mich nur ärgern?
class a
constructor: ->
@foo = foo;
(new a "bar").foo
- Konstruktor
- parameter (@foo): ->
- parameter mit default werten (@foo = "bar"): ->
class a
setFoo: (@foo) -> @
getFoo: -> @foo
(new a "bar").foo
- typisches Beispiel für getter und setter
-
keine private variablen
- Könnt natürlich drum rum bauen
class a
constructor: (@foo = new (
class
a: -> 5
)) ->
(new a).foo.a()
- 1. ein wenig vergewaltigt
- 2. zeigt was möglich ist
- 3. womöglich mitm servicelocator ganz interessant ^^
- 4. parameterreihenfolge
class a
@foo: -> "bar"
a.foo()
- Statische Funktionen
-
Statische Funktionen gibt es in JS nicht
- werden kopiert beim extends
class a
foo: -> "bar"
class b extends a
(new a).foo()
- 1. klassische vererbung
- 2. extends wird nur einmalig embedded
- 3. performant, nur statische methoden werden kopiert
- 4. klasse die extended wird muss vorhanden sein.
class a
constructor: (@dom) ->
@dom.find('.foo').click (e) ->
@handelClickFoo e
handelClickFoo: (e) ->
0
- @entspricht this
- 1. wo ist das Problem?
- 2. => fat arrow
- bei funktion
- bei funktionsdeklaration
real world application
- natürlich im kleinen
- beispiele liegen der Präsentation bei
class main
di: null
getContainer: ->
return @di if @di
@di = new di
@di.configure
factories:
dispatcher: (di)->
new dispatcher di
controllerHello: (di) ->
new controllerHello di.get('serviceGreeter')
serviceGreeter: ->
new serviceGreeter
@di
handle: (request) ->
@getContainer().get('dispatcher')().dispatch request.controller
(new main).handle
controller: 'Hello'
- werfen nur ein blick ins bootstrapping
- getContainer und Handle sind teil des HttpKernelInterfaces
CoffeeScript
using php Storm.
- 1. wer kennt phpstorm file watcher?
- 2. wer nutzt diese?
- Änderung einer Datei triggert ein Programm.
- --bare
- 1. Standadmäßig packt Coffeescript alles in eine anonyme funktion
- Best Practice
- Keine Probleme mit dem Scope
-
1. Welche Probleme treten auf?
- jede Datei liegt einzelnt da
- .map wird nicht geinlinent
- Chaos im Dateisystem
- Abhängigkeit zu PHPStorm
- Abhängigkeiten sind schlecht!
- 1. wir wollen Continuous Integration!
- 2. Continuous deployment
- 3. Jemand Push't und die Magie nimmt ihren Lauf
- 4. Lösung: Commandline!
CoffeeScript
using CoffeeScript.
- CoffeeScript selbst ansehen
- -c COMPILE!
- -o DORECTORY!
clean:
find . -iname "*.js" -exec rm {} \;
find . -iname "*.map" -exec rm {} \;
rm -rf build
js:
coffee -bjc -o build/ \
lib/di.coffee \
lib/dispatcher.coffee \
controller/abstract.coffee \
controller/hello.coffee \
service/greeter.coffee \
main.coffee
run: clean js
reset
node build/.js
...
node build/.js
YAAYYYY!!
hello!! folks
-
1. Wer schreibt Makefiles?
- 1.1 Organisierte Bash Skripte
- 1.2 ich mag sie :)
- 2. rufen wir "make run" auf
- 3. output des Skriptes.
- 4. alle Sourcen sind im Repo!
- -b bare, -j join, -c compile, -o out
gut?
- 1. Reihenfolge muss explizit angegeben werden
js:
coffee -bjc -o build/ \
lib/di.coffee \
lib/dispatcher.coffee \
controller/abstract.coffee \
controller/hello.coffee \
service/greeter.coffee \
main.coffee
- 1. Reihenfolge muss explizit angegeben werden
- Nutzt CommonJS
- Standard für NodeJs Projekte
- Können wir fürs web verwenden
- identishcer Syntax wie nodejs
- npm pakete nutzbar
- viele Standard verfügbar, streams, buffer
- Zum Bundeln nutzen wir Browserify
- Quasi Standard
- Kann Coffeescript
- Auch ohne CoffeeScript geil
- Alternative zu AMD, RequireJs
- Alternative Loader, AMD, ..
_di = require './lib/di.coffee'
_dispatcher = require './lib/dispatcher.coffee'
_controllerLeft = require './controller/left.coffee'
_controllerContent = require './controller/content.coffee'
_controllerFooter = require './controller/footer.coffee'
_serviceGreeter = require './service/greeter.coffee'
class main
di: null
getContainer: ->
return @di if @di
@di = new _di
@di.configure
factories:
dispatcher: (di)->
new _dispatcher di
controllerLeft: (di) ->
new _controllerLeft di.get('serviceGreeter')
controllerContent: (di) ->
new _controllerContent
controllerFooter: (di) ->
new _controllerFooter
serviceGreeter: ->
new _serviceGreeter
@di
handle: (request) ->
@getContainer().get('dispatcher')().dispatchRoute request
app = new main
$('document').ready ->
$('.app_controller').each (i, el) ->
app.handle
controller: $(el).data('controller')
dom: $(el)
Demo?
- im Browser
-
HTML Zeigen
- 3 Controller
- Alle werden dispatcht
-
SourceMaps
- Debuggen von CoffeeScript
- Gebundelt über Browserify via Grunt
- Demo natürlich dabei!
-
via browserify im browser
-
was fehlt?
-
hacky
-
just for fun
-
Demo?
-
make all
-
main zeigen
-
browserify bundelt und embedded die require funktion
-
v8 implementiert nur eine funktion, erste zeile der main zeigen
thx.
@timglabisch
-
Würde mich über Feedback freuen.