Powerful mostly unknown Javascript-Features

Post on 20-Jan-2015

776 views 1 download

Tags:

description

Präsentation zum Thema "Powerful mostly unknown Javascript-Features", gehalten von Entwicklern der Softwareagentur App Aware: Sascha Hameister und Aron Homberg

Transcript of Powerful mostly unknown Javascript-Features

1

Powerful mostly unknown Javascript-Features

1Freitag, 20. November 2009

2

Sascha Hameister

- lebt in Berlin

- Entwickler, App Aware

- über 10 Jahre Entwicklungserfahrung

- Speaker auf Fachkonferenzen

- Autor bei O‘Reilly und Hanser-Verlag

- Fokus: Mobile, Web

2Freitag, 20. November 2009

3

Aron Homberg

- lebt in München

- Entwickler, App Aware

- über 8 Jahre Entwicklungserfahrung

- Speaker auf Fachkonferenzen

- Autor bei O‘Reilly und Hanser-Verlag

- Aktiv in der OpenSource Gemeinschaft

- Fokus: Web, Datenbanken

3Freitag, 20. November 2009

4

Agenda

- Daten über mehrere Aufrufe persistent halten

- Anonyme Funktionen verwenden

- Debugging von Objekten verbessern

- Standard-Verhalten nativer Funktionen ersetzen

- Aufrufhierarchien ohne Temporärvariablen

- Funktionen mit beliebiger Argumentanzahl

- Funktionalität bestehender Funktionen dynamisch erweitern

- Folgefehler durch Objektreferenzierung verhindern

- Keywords

4Freitag, 20. November 2009

5

Daten über mehrere Aufrufe persistent halten

5Freitag, 20. November 2009

6

Daten über mehrere Aufrufe persistent halten

- Gründe

- Persistenz im Client abbilden

- Netzwerktraffic verringern

- Serverlast verringern

6Freitag, 20. November 2009

7

Client Cookies!

7Freitag, 20. November 2009

8

Client Cookies

- Die Anatomie eines Cookies:

- Weitere Parameter:

- Expire date (Default: Zum Ende der Zugriffsphase)

- Path (Default: Aufrufendes Dokument)

- Domain (Default: Aktuelle Domain)

- Secure (Boolscher Parameter: Wird eine verschlüsselte Verbindung benötigt? (HTTPS)

cookieName=cookieValue

8Freitag, 20. November 2009

9

Client Cookies

- Setzen eines lokalen Cookies:

- Das ganze einfach testen:

document.cookie = "dieAntwort=42";

alert(document.cookie);

// Besser (mit Firebug)

>>> console.debug(document.cookie);dieAntwort=42; ... (weitere Cookies)

9Freitag, 20. November 2009

Client Cookies

- Eine schöne Funktion zum speichern:

- Persistenz bis zur nächsten WebTechCon:

function setCookie(name, value, expires, path, domain, secure) { var curCookie = name + "=" + escape(value) + ((expires) ? "; expires=" + expires.toGMTString() : "") + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : ""); document.cookie = curCookie;}

var naechsteWTC = new Date();naechsteWTC.setTime(naechsteWTC.getTime() + 365 * 24 * 60 * 60 * 1000);

setCookie("dieAntwort", 42, naechsteWTC);

10Freitag, 20. November 2009

Client Cookies

- Und das ganze auslesen:

- Achtung: Cookies werden escaped gespeichert und müssen daher durch get/setCookie un/escaped werden.

function getCookie(name) { var dc = document.cookie; var prefix = name + "="; var begin = dc.indexOf("; " + prefix); if (begin == -1) { begin = dc.indexOf(prefix); if (begin != 0) return null; } else begin += 2; var end = document.cookie.indexOf(";", begin); if (end == -1) end = dc.length; return unescape(dc.substring(begin + prefix.length, end));}

11Freitag, 20. November 2009

Client Cookies

- Die Persistenzschicht ist fertig:

- Seite neu laden... und das ganze nochmal:

getCookie("dieAntwort")-> 42 :-)

- Implementiert z.B. im Dojo-Framework im Namespace:dojo.cookie

console.log(getCookie("dieAntwort"));

42

12Freitag, 20. November 2009

13

Anonyme Funktionen verwenden

13Freitag, 20. November 2009

14

Anonyme Funktionen verwenden

- Gründe

- Implizite Codeübergabe

- Funktionalität dynamisch injecten

- Temporärcode ausführen

14Freitag, 20. November 2009

15

Anonyme Funktionen!

15Freitag, 20. November 2009

16

Anonyme Funktionen

- Eine anonyme Funktion kreieren:

- Einer Funktion eine anonyme Funktion übergeben:

(function () { alert("I am unnamed!");}()); // Calls the method directly

var obj = {"answer": 33};

function execOnObject(obj, funcRef) { obj.__jailCode = funcRef; obj.__jailCode(); // Einfache Variante - oder apply/call()}execOnObject(obj, function() { alert(this.answer); // -> 33});

16Freitag, 20. November 2009

17

Anonyme Funktionen

- Iterative Scope-Jail-Execution (z.B. ähnlich dojo.forEach())function forEach(map, code) { for (key in map) { map[key].__jailCode = code; map[key].__jailCode(); } return map;}

var myMap = [{value: 1}, {value: 2}, {value : 3}];

myMap = forEach(myMap, function() { // This references to map iterator while // function execution this.value = this.value * 4;});

console.debug(myMap);

17Freitag, 20. November 2009

18Freitag, 20. November 2009

19

Debugging von Objekten verbessern

19Freitag, 20. November 2009

20

Debugging von Objekten verbessern

- Gründe

- Standard-Debugging-Output von Objekten ist stets[object Object]

- Objekte werden serialisierbar (beispielsweise für den Versand zum Server)

function Person (firstName, lastName) {

}

var p = new Person("Sascha", "Hameister");alert(p); // [object Object]alert(p + " FOO"); // [object Object] FOO

20Freitag, 20. November 2009

21

toString und valueOf!

21Freitag, 20. November 2009

22

toString & valueOf

function Person (firstName, lastName) {

this.toString = function () { return "<Person {firstName: '" + firstName + "', lastName: '" + lastName + "'"} >" }

this.valueOf = function () { return firstName + " " + lastName; }}

var p = new Person("Sascha", "Hameister");

alert(p);// <Person {firstName: "Sascha", lastName: ”Hameister”} >

alert(p + " FOO"); // [object Object] FOO// Sascha Hameister FOO

22Freitag, 20. November 2009

23

Standard-Verhalten nativer Funktionen ersetzen

23Freitag, 20. November 2009

24

Standard-Verhalten nativer Funktionen ersetzen

- Gründe

- alert-, con#rm-, prompt-Funktionen mit eigener Funktionalität ersetzen und Aufrufbarkeit nativer Funktionalität sicherstellen

24Freitag, 20. November 2009

25

Native function overloading!

25Freitag, 20. November 2009

26

Native function overloading

var _alert = window.alert;

function alert(msg) { console.debug(msg);}

alert("FOO"); // Debugs FOO_alert("BAR") // Alerts BAR with native alert-window.

delete window.alert; // Später dazu mehr :)

alert("FOO AGAIN!");

26Freitag, 20. November 2009

27

Aufrufhierarchien ohne Temporärvariablen

27Freitag, 20. November 2009

28

Aufrufhierarchien ohne Temporärvariablen

- Gründe

- Mehrstu#ge Aufrufverkettungen gut leserlich implementieren (beispielsweise bei Graphenzeichnung oder Charting)

28Freitag, 20. November 2009

29

Chaining!

29Freitag, 20. November 2009

30

Chaining

- Verkettete Funktionsaufrufe de#nieren:

var validValues = new Array( {valid: false, value: 0}, {valid: true, value: 1}

).filter(function(ele) {

if (ele.valid) {return ele}

}).map(function(ele) {

return ele.value;

}).toString();

console.log(validValues); // -> 1

30Freitag, 20. November 2009

31

Chaining

- Pro‘s:

- Sehr gut anwendbar, um temporäre Variablen zu vermeiden

- Kann bei kleinen Chains die Lesbarkeit erhöhen

- Automatisches „delete“ der - implizit nicht deklarierten - Temporärvariablen (Speicherschonend, weniger Code!)

- Con‘s:

- Achtung bei „unde#ned“ returns!

- Achtung bei zu langen Verkettungen! (Lesbarkeit)

31Freitag, 20. November 2009

32

Funktionen mit beliebiger Argumentanzahl

32Freitag, 20. November 2009

33

Funktionen mit beliebiger Argumentanzahl

- Gründe

- Realisierung von Funktionen wie printf

- Realisierung von Funktionen ohne benamte Parameter

33Freitag, 20. November 2009

34

arguments!

34Freitag, 20. November 2009

35

arguments

- Beliebige Argumentanzahlen verarbeiten:

- „arguments“ ist ein Keyword im Funktionskontext

- Es ist als Array iterierbar (arguments.length, arguments[i])

function lotOfArgs(){ console.debug(arguments);}lotOfArgs("A", "B", 3, 4, 20, true, /rg/);

-> ["A", "B", 3, 4, 20, true, /rg/]

35Freitag, 20. November 2009

36

arguments

- Tracing des Aufrufers & Dynamische Rekursion:

- arguments.callee references calling function and scope

var maxThiefTry = 3;function thief() { attractOfficer();}

function attractOfficer() { maxThiefTry--; console.log("Arrest thief in... " + maxThiefTry + "times!"); if (maxThiefTry > 0) { arguments.callee(); } else { console.log("Thief arrested!") }} thief();

36Freitag, 20. November 2009

37

arguments

- Drei Chancen hatte er ;-)

- Die Aufgerufene Funktion ruft den Aufrufer dynamisch auf und muss nichts über dessen Funktionsnamen etc. wissen.

- Es lassen sich so endliche und unendliche dynamische Rekursionsschleifen bzw. Ping-Pongs erstellen.

Arrest thief in... 2times!Arrest thief in... 1times!Arrest thief in... 0times!Thief arrested!

37Freitag, 20. November 2009

38

Funktionalität bestehender Funktionen dynamisch erweitern

38Freitag, 20. November 2009

39

Funktionalität bestehender Funktionen dynamisch erweitern

- Gründe

- Bestehende Funktionen nicht weiter aufblähen

- Mixen mehrerer Funktionalitäten zu einer neuen Funktion

39Freitag, 20. November 2009

40

Delegation!

40Freitag, 20. November 2009

41

Delegation

- Funktionen miteinander vereinen (Mixing)

- „func3()“ ruft „func1()“ und „func2()“ mit seinen Aufrufparametern auf!

function delegate() { var stack = arguments;

return function() { for (var i=0; i<stack.length; i++) { stack[i](arguments); } };}var func1 = function() {console.debug(arguments)};var func2 = function() {console.debug(arguments)};

func3 = delegate(func1, func2);func3("C");

41Freitag, 20. November 2009

42

Folgefehler durch Objektreferenzierung verhindern

42Freitag, 20. November 2009

43

Folgefehler durch Objektreferenzierung verhindern

- Standard: Mit Referenzen arbeiten:

- Achtung: Versteckte Bugs! Durch die Verwendung als Referenz wurde das Objekt Aron ebenfalls manipuliert!

- Skalare Typen werden immer kopiert, nie referenziert.

var aron = {name: "Aron Homberg"};var sascha = aron;sascha.name = "Sascha Hameister";

console.debug(aron);

-> aron.name -> „Sascha Hameister“

43Freitag, 20. November 2009

44

Objekte klonen!

44Freitag, 20. November 2009

Objekte klonen

- Lösung: Objekte und ihre Attribute (1st-Level) klonen!

- Diese Funktion klont lediglich die erste Attribut-Ebene eines Objekts. In tieferen Ebenen blieben Referenzen erhalten.

function clone(props) { var tobj = {}; for(var x in props){ tobj[x] = props[x]; } return tobj;}var aron = {name: "Aron Homberg"};var sascha = clone(aron);sascha.name = "Sascha Hameister";

console.debug(aron);

-> aron.name -> „Aron Homberg“ // Bleibt unverändert!

45Freitag, 20. November 2009

46

Keywords

46Freitag, 20. November 2009

47

Keywords

- instanceof

- typeof

- with

- delete

- in

- continue

- new

47Freitag, 20. November 2009

48

Keyword: instanceof

48Freitag, 20. November 2009

49

Keyword: instanceof

var example = 'FOO';alert(example instanceof String); // false

var example = new String('FOO');alert(example instanceof String); // true

- Gibt true zurück, wenn das Objekt die Instanz einer gegebenen Klasse ist.

49Freitag, 20. November 2009

50

Keyword: typeof

50Freitag, 20. November 2009

51

Keyword: typeof

var example = 'FOO';alert(typeof example); // string

var example = 10;alert(typeof example); // number

var example = true;alert(typeof example); // boolean

var example = /foo/igalert(typeof example); // object

var example = [];alert(typeof example); // object

var example = {};alert(typeof example); // object

51Freitag, 20. November 2009

52

Keyword: with

52Freitag, 20. November 2009

53

Keyword: with

with (document.getElementById('example')) {innerHTML = 'HTML INHALT';style.color = '#123456';style.height = '20px';

}

53Freitag, 20. November 2009

54

Keyword: delete

54Freitag, 20. November 2009

55

Keyword: delete

- Per delete können Zuweisungen aller Art hart gelöscht werden:

Mit „delete“ lässt sich Speicher freiräumen. Temporärvariablen bei Iterationen sollten so immer „Garbage collected“ werden.

var object = {attribute1 : 'value1',attribute2 : 'value2'

};

delete object.attribute1;

55Freitag, 20. November 2009

56

Keyword: delete

var anArray = ['foo', 'bar'];

delete anArray[1];

for (var i = 0; i < anArray.length; i++) {console.log(anArray[i]); // foo, undefined

}

- Aufpassen bei Arrays oder Iterationen!

Es wird hart gelöscht. Eine Änderung der Indizes oder des length-Attributes des Arrays erfolgt nicht!

56Freitag, 20. November 2009

57

Keyword: delete

- ACHTUNG: delete() löscht je nach Implementation (Javascript-VM / Interpreter) hart die Referenz aus dem Memory.

- Bei Zugriff auf einen so gelöschten Wert können dadurch kritische Interpreter / VM-Runtime Execution Fehler auftreten.

57Freitag, 20. November 2009

58

Keyword: in

58Freitag, 20. November 2009

59

Keyword: in

var object = {attribute1 : 'value1',attribute2 : 'value2'

};

'attribute1' in object // TRUE

var object = {attribute1 : 'value1',attribute2 : 'value2'

};

var idx;for (idx in object) {

alert(object[idx]); // two alerts… value1, value2}

59Freitag, 20. November 2009

60

Keyword: in (Prototypes!)

Object.prototype.example = function () {};

var object = {attribute1 : 'value1',attribute2 : 'value2'

};

var idx;for (idx in object) {

alert(object[idx]); // Was erwarten Sie?}

value1value2function () {}

60Freitag, 20. November 2009

61

Keyword: in (Prototypes!)

- Bei der Nutzung von in bei jedem Cycle Plausibilitätsprüfung des aktuellen Typs

Object.prototype.example = function () {};

var object = {attribute1 : 'value1',attribute2 : 'value2'

};

var currentObject;var idx;for (idx in object) {

currentObject = object[idx];if (typeof currentObject === 'string') {

alert(object[idx]); // two alerts… value1, value2}

}

61Freitag, 20. November 2009

62

Keyword: continue

62Freitag, 20. November 2009

63

Keyword: continue

outerLabel: for (var i = 0; i < 5; i++) {innerLabel: for (var j = 0; j < 5; j++) {

if (j == 2) {continue outerLabel;

} }}

63Freitag, 20. November 2009

64

Keyword: new

64Freitag, 20. November 2009

65

Keyword: new

function MyClass () {}

var foo = new MyClass();

var bar = MyClass();

// Unterschied?

function MyClass () { if (!(this instanceof MyClass)) { throw 'You tried to instantiate MyClass without new.'; }}

65Freitag, 20. November 2009

66

Powerful known Javascript-Features!

Vielen Dank! :-)

66Freitag, 20. November 2009