Post on 20-Jan-2015
description
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