T2 s4 javascriptfuerfortgeschrittene

64
Innovative Software-Lösungen. www.assono.de EntwicklerCamp 2010 Track 2, Session 4: JavaScript für Fortgeschrittene Gelsenkirchen, 9. März 2010

description

 

Transcript of T2 s4 javascriptfuerfortgeschrittene

Page 1: T2 s4 javascriptfuerfortgeschrittene

Innovative Software-Lösungen.

www.assono.de

EntwicklerCamp 2010Track 2, Session 4:JavaScript für Fortgeschrittene

Gelsenkirchen, 9. März 2010

Page 2: T2 s4 javascriptfuerfortgeschrittene

Seite 2www.assono.de

Thomas Bahn

Diplom-Mathematiker, Universität Hannover

seit 1997 entwickle ich mit Java und relationalen Datenbanken

seit 1999 mit Notes/Domino zu tun: Entwicklung, Administration, Beratung und Schulungen

regelmäßiger Sprecher auf nationalen und internationalen Fachkonferenzen zu IBM Lotus Notes/Domino und Autor für THE VIEW

[email protected]://www.assono.de/blog04307/900-401

Page 3: T2 s4 javascriptfuerfortgeschrittene

Seite 3www.assono.de

Variablendeklaration

- Variablen-Deklaration:var name;

- Variablen-Deklaration kombiniert mit Wertzuweisung:var name = wert;

- SSJS-Spezialität: typisierte Variablen-Deklaration:var name : typ = wert;

- Prüfung, ob Variable deklariert ist- häufig, aber vereinfacht: if (a) {...}- Vorsicht: der Block wird auch ausgeführt, wenn a

gleich false, null, "" oder 0 ist

- besser: if (typeof a !== „undefined“) {...}

Page 4: T2 s4 javascriptfuerfortgeschrittene

Seite 4www.assono.de

Variablentypen

- „loose typing“ heißt nicht untypisiert!

- Es gibt folgende 6 Typen:- Strings- Numbers- Booleans- Objects- null- undefined

Page 5: T2 s4 javascriptfuerfortgeschrittene

Seite 5www.assono.de

Spezielle Strings

- \ Maskierungszeichen

- \\ ein Rückwärtsstrich \

- \' ein einfacher Anführungsstrich

- \" ein doppelter Anführungsstrich

- \n neue Zeile (newline)

- \r “Wagenrücklauf“ (carriage return)

- \t Tabulator

- \u Unicode-Zeichen, z. B. \u042F => Я

Page 6: T2 s4 javascriptfuerfortgeschrittene

Seite 6www.assono.de

Zahlen

- alle Zahlen sind 64-bit Gleitkommazahlen („double“)

- Rundungsdifferenzen durch Binär-Dezimal-Konvertierung

- Bit-Shifting (<<, >>) möglich, aber kontraproduktiv

Page 7: T2 s4 javascriptfuerfortgeschrittene

Seite 7www.assono.de

Zahlen (forts.)

- 0x Präfix für Hexadezimalzahl-Literale, z. B. 0xFF0 Präfix für Oktalzahl-Literale, z. B. 014 (=12)

- Achtung bei parseInt(), z. B. parseInt(08) => Fehler!,insbesondere bei Benutzereingaben, z. B. beim Monat

- daher besser immer bei parseInt() die Basis (radix) als zweiten Parameter mit angeben:parseInt("08", 10);

Page 8: T2 s4 javascriptfuerfortgeschrittene

Seite 8www.assono.de

Zahlen (forts.)

- NaN = Not a Number

- „ansteckend“- ungleich allem anderen (inklusive NaN)

- testen mit isNaN()- typeof NaN => "number"

Page 9: T2 s4 javascriptfuerfortgeschrittene

Seite 9www.assono.de

Zahlen (forts.)

- Infinity = unendlich,

- z. B. a/0 => Infinity- zumindest größer als die größte gültige Zahl: Infinity > 1.7976931348623157e+308

- -Infinity- ist absolut kleiner als die kleinste gültige Zahl:5e-324 > -Infinity

- beide „ansteckend“ bei Berechnungen, aber- 1/Infinity => 0- Infinity/Infinity => NaN

Page 10: T2 s4 javascriptfuerfortgeschrittene

Seite 10www.assono.de

Boolean

- ! logisches Nicht

- && logisches Und

- || logisches Oder

- „lazy evaluation“: nur berechnen, wenn noch nötig

- Beispiel:var a = 1; true || (a = 2) => a ist noch 1

Page 11: T2 s4 javascriptfuerfortgeschrittene

Seite 11www.assono.de

„Falsche“ Werte

- Folgende Werte sind „falsch“ (falsy):- false- null („leer“, bewusst gesetzt)

- undefined (uninitialisiert oder nicht vorhanden)

- "" (leere Zeichenkette)- 0- NaN

- Alle anderen Werte sind true, auch- "0"- "false"

Page 12: T2 s4 javascriptfuerfortgeschrittene

Seite 12www.assono.de

Vergleiche

- == Gleichheit ggf. nach Typumwandlung

- != Ungleichheit ggf. nach Typumwandlung

- === Gleichheit ohne Typumwandlung

- !== Ungleichheit ohne Typumwandlung

- Beispiele- "1" == 1 ist wahr

- "1" === 1 ist falsch

Page 13: T2 s4 javascriptfuerfortgeschrittene

Seite 13www.assono.de

Vergleiche (forts.)

- switch- Vergleich ohne Typumwandlung

- a ? b : c- ternärer Operator- wenn a wahr ergibt, ist das Ergebnis b, sonst c

Page 14: T2 s4 javascriptfuerfortgeschrittene

Seite 14www.assono.de

Guard-Operator: &&- && ist logisches Und

- Beispiel:return obj && obj.member;

- gibt obj.member zurück, wenn obj nicht undefined oder null ist (oder präziser: nicht false ist)

- aber Vorsicht, wenn false, null, "", 0 gültige Werte sein können!

Page 15: T2 s4 javascriptfuerfortgeschrittene

Seite 15www.assono.de

Default-Operator: ||- || ist logisches Oder

- Beispielvar value = arg || "Vorgabewert";

- wenn arg nicht „falsch“ ist, wird value arg zugewiesen, sonst "Vorgabewert"

- aber Vorsicht, wenn false, null, "", 0 gültige Werte sein können!

- nützlich bei optionalen Parametern einer Funktion

Page 16: T2 s4 javascriptfuerfortgeschrittene

Seite 16www.assono.de

Noch mehr Operator-Magie

- + als unärer Operator wandelt Strings um in Zahlen: +"1" === 1

- !! wandelt um in Boolean: !!"1" === true

Page 17: T2 s4 javascriptfuerfortgeschrittene

Seite 17www.assono.de

typeof-Operator

- Die Ergebnisse von typeof helfen nicht immer weiter

Typobjectfunctionarray "object"numberstringbooleannull "object"undefined

Ergebnis von typeof"object""function"

"number""string""boolean"

"undefined"

Page 18: T2 s4 javascriptfuerfortgeschrittene

Seite 18www.assono.de

Schleifen

- for (initialisierung; vergleich; inkrement) {...}

- alle drei Elemente können durch Komma (!) getrennt mehrere Anweisungen enthalten, z. B.

- for (var i = 0, result = ""; i < 100; i++, result += i + "\n"

) {...}

Page 19: T2 s4 javascriptfuerfortgeschrittene

Seite 19www.assono.de

Die with-Falle

- with (obj) {member = "Wert";

}- wenn obj das Attribut member enthält, wird dieses

gesetzt

- sonst eine globale Variable namens member!

Page 20: T2 s4 javascriptfuerfortgeschrittene

Seite 20www.assono.de

Falle Semikolon-Einfügung

- Wenn ein Fehler auftritt, versucht der Interpreter es noch einmal, nachdem er vor dem nächsten Zeilenumbruch ein Semikolon eingefügt hat.

- Beispiel:return // hier wird ein Semikolon eingefügt{ // wird als Block interpretiert

status: "ok" // status ist ein Label und // Semikolon wird eingefügt

}; // Block wird nie ausgeführt- Das kann auch Fehler maskieren.

Page 21: T2 s4 javascriptfuerfortgeschrittene

Seite 21www.assono.de

Referenzen

- Variablen enthalten Referenzen

- Funktionsparameter immer Referenzen, nicht Werte

Page 22: T2 s4 javascriptfuerfortgeschrittene

Seite 22www.assono.de

Funktionen sind Objekte

- Funktionen sind Daten.

- Funktionen können in Variablen gespeichert werden.

- Funktionen können als Argumente übergeben werden.

- Funktionen können Attribute und Methoden (also innere Funktionen) haben.

Page 23: T2 s4 javascriptfuerfortgeschrittene

Seite 23www.assono.de

Definition von Funktionen

- function f (arg) { ... } ist Abkürzung fürvar f = function f(arg) { ... }

- anonyme Funktionvar f = function (arg) { ... }

- innere Funktionfunction f() {

...function g() { ... }...

}

- new Function f(arg, body)

Page 24: T2 s4 javascriptfuerfortgeschrittene

Seite 24www.assono.de

Funktionsparameter

- Deklaration enthält Liste der erwarteten Parameter

- Zugriff auf alle Parameter mit arguments, einem Array-ähnlichen Konstrukt

- Beispiel:function sum() {

var i, result = 0;for (i = 0; i < arguments.length; i++) {

result += arguments[i];}return result;

}sum(1, 2, 3, 4, 5);

Page 25: T2 s4 javascriptfuerfortgeschrittene

Seite 25www.assono.de

Funktionsrückgabe

- Funktionen ohne return geben undefined zurück.

- Funktionen mit return x geben x zurück.

- Konstruktoren (später mehr) geben ohne return einen Verweis auf das neue Objekt zurück.

- Konstruktoren mit return x geben x zurück, wenn x ein Objekt ist, sonst das neue Objekt.

Page 26: T2 s4 javascriptfuerfortgeschrittene

Seite 26www.assono.de

Anonyme Funktionen

- als Parameter für andere Funktionen- wenn sie nur dafür gebraucht werden- innerhalb der aufgerufenen Funktion haben sie

dann einen Namen- Beispiel: Call-Back-Funktionen bei Ajax-Aufrufen

bei setTimeout() oder setInterval()- setTimeout(

function(){console.log(new Date());}, 1000)

Page 27: T2 s4 javascriptfuerfortgeschrittene

Seite 27www.assono.de

Anonyme Funktionen (forts.)

- zum sofortigen, einmaligen Ausführen- z. B. für Initialisierung- zum Schutz von lokalen Variablen, die dann nur

über innere Funktionen zugänglich sind- Beispiel:function Mensch(name) {this.getName = function() {return name};this.setName =

function (newName) {name = newName};};var me = new Mensch("Thomas");me.getName();

- lokale Variable name nur noch über setName() änderbar, also geschützt

Page 28: T2 s4 javascriptfuerfortgeschrittene

Seite 28www.assono.de

„eval is evil“

- Performance

- Sicherheit: nur auf vertrauenswürdige Argumente anwenden

Page 29: T2 s4 javascriptfuerfortgeschrittene

Seite 29www.assono.de

alert()- „Hilfsdebugger“

- blockiert Programmausführung

- Vorsicht bei asynchronen Ajax-Aufrufen

Page 30: T2 s4 javascriptfuerfortgeschrittene

Seite 30www.assono.de

- nur zwei Arten von Scopes:- global- Funktion

- insbesondere kein „Block-Scope“, wie z. B. in Java

- Zugriff auf undeklarierte Variable erzeugt neue globale Variable (z. B. bei Schreibfehler), aber auch function () {

a = 1;}

Scopes

Page 31: T2 s4 javascriptfuerfortgeschrittene

Seite 31www.assono.de

- ein unerwarteter Effekt:var a = 1;function f() {

alert(a);var a = 2;alert(a);

}f();

- Ergebnis: undefined (!) und 2- offenbar 2 Phasen:

- lokalen Variablen finden und reservieren, dann - Block ausführen

Scopes (forts.)

Page 32: T2 s4 javascriptfuerfortgeschrittene

Seite 32www.assono.de

- jedes Objekt hat eigenen Kontext

- globaler Kontext

- Funktionen haben Zugriff auf Attribute und Methoden des Kontexts, in dem sie definiert wurden...

- und weiter „nach oben“ bis zum globalen Kontext.

- Bei Browsern ist das window-Objekt der globale Kontext!

- Beispiel:a = 1;alert(window.a); => 1

Kontext

Page 33: T2 s4 javascriptfuerfortgeschrittene

Seite 33www.assono.de

Funktionsaufruf

- Funktionen laufen immer in einem Kontext.

- this zeigt immer auf den aktuellen Kontext.

- innere Funktionen können nicht auf this der übergeordneten Funktion zugreifen

- Konvention: var that = this;- 4 Arten, Funktionen aufzurufen:

Page 34: T2 s4 javascriptfuerfortgeschrittene

Seite 34www.assono.de

Funktionsaufruf (forts.)

- Funktionsform f(args): f wird ausgeführt im globalen Kontext.

- Methodenform obj.f(args) und obj["f"](args): f wird ausgeführt mit obj als Kontext.

- Vorsicht Falle:vergisst man das Objekt anzugeben, läuft f im globalen Kontext u. U. fehlerfrei durch

Page 35: T2 s4 javascriptfuerfortgeschrittene

Seite 35www.assono.de

Funktionsaufruf (forts.)

- Konstruktor-Form new f(args):f läuft im Kontext eines neu erstellten Objekts, das auch Rückgabewert der Funktion ist.

- f.apply(obj, args):f läuft im Kontext von obj.f braucht dazu nicht Methode von obj zu sein!

- Beispiel:folgt auf Folie zu Funktionsparametern

Page 36: T2 s4 javascriptfuerfortgeschrittene

Seite 36www.assono.de

Currying

- Man erzeugt zu einer Funktion mit mindestens einem Parameter eine neue Funktion mit mindestens einem Parameter weniger.

- Beispiel: function addGenerator(a) {

return function(b) {return a + b;

}; };addOne = addGenerator(1);var test = addOne(47); // ergibt 48

Page 37: T2 s4 javascriptfuerfortgeschrittene

Seite 37www.assono.de

Closures

- Zugriff auf Attribute und Methoden der übergeordneten Funktion bleibt auch nach deren Ende erhalten.

- Das nennt man Closure.

- Beispiel:tbd.

Page 38: T2 s4 javascriptfuerfortgeschrittene

Seite 38www.assono.de

Objekte

- Objekte sind Mengen von Name-Wert-Paaren

- Namen sind Strings, Werte von beliebigen Typen

- „assoziative Arrays“ oder „Hash Maps“

Page 39: T2 s4 javascriptfuerfortgeschrittene

Seite 39www.assono.de

Erzeugen von Objekten

- Objekt-Literale wie {}

- new

- Object.create(...)

Page 40: T2 s4 javascriptfuerfortgeschrittene

Seite 40www.assono.de

Objekt-Literale und Zugriff auf Mitglieder

- var obj = {vorname : "Thomas", "Ort der Geburt": "Gehrden"

}

- Dann ist obj.vorname gleich "Thomas" undobj["Ort der Geburt"] gleich "Gehrden"

Page 41: T2 s4 javascriptfuerfortgeschrittene

Seite 41www.assono.de

Konstruktoren

- Funktionen können in Kombination mit new als Konstruktor verwendet werden.

- Es wird ein neues, leeres Objekt erzeugt und die Funktion in seinem Kontext ausgeführt.

- Vorgabe-Rückgabewert eines Konstruktors ist this, also das erzeugte Objekt.

Page 42: T2 s4 javascriptfuerfortgeschrittene

Seite 42www.assono.de

Konstruktoren (forts.)

- Objekte haben das constructor-Attribut, das auf ihren Konstruktor zeigt.

- Konvention: Konstruktoren werden groß geschrieben.

- Vorsicht Falle: vergisst man new, wird die Funktion einfach im globalen Kontext ausgeführt (kein Fehler)

Page 43: T2 s4 javascriptfuerfortgeschrittene

Seite 43www.assono.de

for ... in-Schleife

- Schleife über alle Attribute und Methoden eines Objekts und seiner Vorfahren(!)

- obj.hasOwnProperty("name")

Page 44: T2 s4 javascriptfuerfortgeschrittene

Seite 44www.assono.de

Erweitern von vorhandenen Objekten

- auch von „Produkt“-Objekten, die zur Sprache gehören, z. B. Function, Object, String!

- Beispiel:String.prototype.trim = function() {

return this.replace(/^\s+|\s+$/g, "");}alert("'" + " test ".trim() + "'");

Page 45: T2 s4 javascriptfuerfortgeschrittene

Seite 45www.assono.de

Arrays

- Arrays sind Objekte (erben von Object)

- haben length-Attribut, immer eins größer, als größter (Ganzzahl-)Index

- Indexe werden umgewandelt in Strings!

- Array-Literale: ["eins", "zwei", "drei"]

- Strings lassen sich nutzen wie Zeichen-Arrays:var text = "abcd"; text[2] => "c"

Page 46: T2 s4 javascriptfuerfortgeschrittene

Seite 46www.assono.de

Die delete-Falle

- delete arr[2]

- löscht das 3. Element, genauer: setzt es auf undefined, es bleibt ein Loch: arr[2] ist undefined, arr[3] bleibt unverändert

- arr.splice(2, 1)entfernt das 3. Element und nachfolgende Elemente rücken auf

Page 47: T2 s4 javascriptfuerfortgeschrittene

Seite 47www.assono.de

Funktionsparameter

- Argumente stehen (zusätzlich) in Quasi-Array arguments.

- Es gibt arguments.length, aber nicht die anderen Array-Methoden.

- Ausweg: Function.prototype.apply()function f() {

var slice = Array.prototype.slice;var argsWithoutFirst =

slice.apply(arguments, [1]);...

}

Page 48: T2 s4 javascriptfuerfortgeschrittene

Seite 48www.assono.de

Öffentliche Attribute und Methoden (public)

- Grundsätzlich sind alle Properties, also Attribute und Methoden eines Objekts öffentlich sichtbar.

Page 49: T2 s4 javascriptfuerfortgeschrittene

Seite 49www.assono.de

Private Attribute und Methoden

- Im Konstruktor definierte Variablen und Funktionen werden zu privaten Attributen und Methoden aller damit erzeugter Objekte.

- Argumente des Konstruktors werden zu privaten Attributen.

- Nur innere Funktionen des Konstruktors können auf private Attribute zugreifen.

Page 50: T2 s4 javascriptfuerfortgeschrittene

Seite 50www.assono.de

Priviligierte Methoden

- Priviligierte Methoden sind öffentlich aufrufbar und haben gleichzeitig auch Zugriff auf private Attribute und Methoden.

- Beispiel:obj = {

var privVariable = "private Variable";this.pubMethode = function () {

alert(privVariable);};

}

- funktionieren über Closures!

Page 51: T2 s4 javascriptfuerfortgeschrittene

Seite 51www.assono.de

„Klassenattribute“

- In Java gibt es den static-Modifier für Klassen-Attribute und -Methoden.

- In JavaScript gibt es keine Klassen, aber...

- man kann den Konstruktoren Attribute hinzufügen und hat damit fast so etwas wie Klassenattribute.

Page 52: T2 s4 javascriptfuerfortgeschrittene

Seite 52www.assono.de

„Klassenattribute“ (forts.)

- Beispiel (tbd.):var obj = {

anzahlObjekte: 0;erzeugeObjekt: function(){

++anzahlObjekte;...

};holeAnzahlObjekte: function() {

return "Es wurden " + anzahlObjekte + " Objekte erzeugt.";

}}

Page 53: T2 s4 javascriptfuerfortgeschrittene

Seite 53www.assono.de

Vererbung a la JavaScript

- jedes Objekt hat das prototype-Attribut

- Suchreihenfolge für Attribute und Methoden:- aktuelles Objekt a- a.prototype- a.prototype.prototype- usw.- bis zuletzt Object.prototype

Page 54: T2 s4 javascriptfuerfortgeschrittene

Seite 54www.assono.de

Prototypische Vererbung

- Attribute und Methoden, die man dem Prototype-Objekt hinzufügt, werden „vererbt“ an alle damit erstellten Objekte.

- auch lange nach der Erzeugung der Objekte!

- obj.prototype.neueFunktion = function () {...};

obj.neueFunktion(...);

- neueFunktion wird nicht direkt in obj, aber über die Prototype-Kette gefunden und dann ausgeführt.

Page 55: T2 s4 javascriptfuerfortgeschrittene

Seite 55www.assono.de

Prototypische Vererbung (forts.)

- Beispiel:var Person = function (name) {

this.name = name;};Person.prototype.getName = function () {

return this.name;};var Benutzer = function(name, passwort) {

this.name = name;this.password = passwort;

};Benutzer.prototype = new Person();var ich = new Benutzer("Thomas", "geheim");alert("Benutzer " + ich.getName + " erstellt");

Page 56: T2 s4 javascriptfuerfortgeschrittene

Seite 56www.assono.de

Klassische Vererbung nachgebaut

- verschiedene Ansätze, die klassische = klassen-basierte Vererbung in JavaScript nachzubauen- nach Douglas Crockford- nach Markus Nix- mit Prototype- u.v.a.m.

Page 57: T2 s4 javascriptfuerfortgeschrittene

Seite 57www.assono.de

Klassische Vererbung nach Crockford

- 3 Erweiterungen von FunctionFunction.prototype.method = function (name, func) { this.prototype[name] = func; return this; // nützlich für's Verketten};Function.method("inherits", function(parent) { this.prototype = new parent(); return this;}; // vereinfachte Version ohne uber();Function.method("swiss", function (parent) { for (var i = 1; i < arguments.lenght; i += 1) { var name = arguments[i]; this.prototype[name] = parent.prototype[name]; }; return this;};

Page 58: T2 s4 javascriptfuerfortgeschrittene

Seite 58www.assono.de

Klassische Vererbung nach Crockford (forts.)

- Anwendungsbeispielvar Person = function(name){this.name = name;};Person.method("getName", funtion() {

return this.name;};var Benutzer = function(name, passwort) {

this.name = name;this.password = passwort;

};Benutzer.inherits(Person);Benutzer.method("getPasswort", function() {

return this.passwort;};

Page 59: T2 s4 javascriptfuerfortgeschrittene

Seite 59www.assono.de

Parasitäre Vererbung

- Rufe im Konstruktor einen anderen Konstruktor auf und gebe das von ihm erzeugte Objekt nach Erweiterung zurück (statt des neu erzeugten Objekts).

- Beispiel:function NeuerKonstruktor() {

var that = VorhandenerKonstruktor();that.weitereMethode = function () {...};return that; // statt implizit this

}

Page 60: T2 s4 javascriptfuerfortgeschrittene

Seite 60www.assono.de

Globale Variablen

- Globale Variablen sind böse und zu vermeiden.

- Probleme, wenn z. B. mehrere Bibliotheken die gleichen globalen Variablen benutzen.

- unvorhersehbare Ergebnisse

Page 61: T2 s4 javascriptfuerfortgeschrittene

Seite 61www.assono.de

Namespaces

- Namensräume helfen, den globalen Kontext sauber zu halten.

- Beispiel:var de = {};de.assono = {};de.assono.HtmlHelper = {

appendDiv: function(toElement) {...};...

}

Page 62: T2 s4 javascriptfuerfortgeschrittene

Seite 62www.assono.de

Alternative: Code „verstecken“

- Mit anonymer Funktion kann man Code „verstecken“

- Beispiel:(function () {

var nachricht = "Hallo Welt!";window.onload = function () {

alert(nachricht);};

})(); // Funktion definieren & ausgeführen

Page 63: T2 s4 javascriptfuerfortgeschrittene

Seite 63www.assono.de

Quellen

- Douglas Crockford: „JavaScript: The Good Parts“

- seine Web-Seiten

- „JavaScript Pro Techniques“

- „JavaScript-Überblick“