Anzeige
Tutorialbeschreibung

Javascript und Ajax - Objekte und Arrays

Javascript und Ajax - Objekte und Arrays

Das nun folgende Tutorial ist ein Auszug aus der 7. Auflage des Buches: JavaScript und Ajax von Christian Wenz.

Kapitel 13 Objekte und Arrays

Bei OOP (Objektorientierte Programmierung) scheiden sich die Geister – die herrschenden Meinungen schwanken zwischen »die Zukunft der professionellen Webentwicklung« bis hin zu »völlig unnötig«. Wir mischen uns in diese Diskussion nicht ein, denn beide Auffassungen haben etwas für sich. Ja, im professionellen Bereich geht es mittlerweile kaum ohne die OOP, mit der sich Funktionalität wunderbar strukturieren lässt. Aber: Ein Großteil der heutigen JavaScript-Programmierung ist nicht so umfangreich, dass man wirklich OOP bräuchte. Insofern: Wägen Sie Aufwand und Nutzen genau ab.

Doch zurück zum Thema, beziehungsweise zum durchgängigen Anwendungsbeispiel in diesem Kapitel. Historisch gesehen hat die Unterstützung von Arrays in JavaScript eine bewegte Geschichte hinter sich. In ganz alten Versionen waren Arrays nur über Umwege möglich, dann gab es eine Zeit lang herbe Unterschiede zwischen den einzelnen Browsern. Mittlerweile ist die Situation schon besser geworden, doch gerade bei Arrays gibt es so viel praktische Funktionalität, die in JavaScript selbst eigentlich keinen Platz mehr hatte.

Damit sind Arrays ein wunderbares Beispiel, um zu demonstrieren, wie Sie eigene Objekte erstellen können. Wir bauen uns unser eigenes Array-Objekt, das viel zusätzliche Funktionalität aufweist. Ganz nebenbei sehen Sie anhand eines praktischen Beispiels diverse OOP-Features von JavaScript. Zunächst lernen Sie auch einige der fortgeschritteneren Array-Funktionen kennen.


13.1 Array-Erweiterungen  

Wie bereits erwähnt wurde, kann man folgendermaßen eine Instanz eines Arrays erstellen:

var a = new Array();

Werden Parameter übergeben, so wird das Array vorausgefüllt:

var a = new Array(1, 2, 3, "abc");

In neueren JavaScript-Versionen kann ein Array auch so initialisiert werden:

var a = [1, 2, 3, "abc"];

In der Eigenschaft length des Arrays wird die Anzahl der Elemente festgesetzt. Verringert man beispielsweise diese Eigenschaft, so werden die letzten Elemente des Arrays dementsprechend gelöscht. An sich hat ein Array aber beliebig viele Elemente. Wird ein zu großer Index für ein Element verwendet, so wird length dementsprechend angepasst. Nach den folgenden beiden Zeilen ist a.length gleich fünf:

var a = new Array(1, 2, 3);
a[4] = 42;


13.1.1 Einfügen, nicht anfügen  

In der JavaScript-Version 1.0 waren die Arrays eher unflexibel. Der Programmierer konnte am Ende Daten anfügen und (durch Setzen der length-Eigenschaft) hinten Daten löschen, aber ein Einfügen von Daten in der Mitte beispielsweise gestaltete sich zunächst etwas schwierig. Man musste hier einen etwas umständlichen Weg gehen: Das Array musste zuerst vergrößert werden (am besten, indem die length-Eigenschaft um eins erhöht wird), dann mussten alle Daten ab der Einfügestelle um eins nach hinten kopiert werden. Abschließend wurden die neuen Daten an die entsprechende Stelle im Array gesetzt. Die folgende Funktion bietet diese Funktionalität; als Parameter müssen das Array, die Einfügestelle und die Daten übergeben werden. Die Funktion gibt das modifizierte Array zurück:

function einfuegen(_array, _position, _datum) {
   _array.length ++;
   for (var i = _array.length – 1; i >= position; i--) {
      _array[i+1] = _array[i];
   }
   _array[_position] = _datum;
   return _array;
}


13.1.2 Anfügen und löschen  

Auch mit den neueren JavaScript-Versionen ist es nicht möglich, direkt mitten in einem Array Elemente einzufügen. Jedoch gibt es neue Methoden, mit denen Elemente bequem an ein Array angehängt oder aus ihm gelöscht werden können. Wenn wir Karten mischen, werden diese Methoden noch einmal interessant werden.

Eine komplette Auflistung der Methoden finden Sie in der Referenz. Exemplarisch werden hier nur die Funktionen vorgestellt, die für das Beispiel von Bedeutung sein werden. Die folgenden Methoden sind alle seit JavaScript 1.2 möglich und sind (im Gegensatz zur Funktion einfuegen() oben) alle Methoden des Array-Objekts.

Microsoft hat an dieser Stelle übrigens eine Zeit lang geschlafen: Die neuen Funktionen sind – sofern nicht anders vermerkt – erst ab Internet Explorer 5.5 in der JScript-Implementierung enthalten. Wenn Sie also auf diese Funktionalitäten Wert legen, sollten Sie das Kapitel bis zum Ende durchlesen, um zu erfahren, wie Sie sie auch auf älteren Browsern implementieren können.

Mit der Methode push() werden Elemente hinten an ein Array angehängt. Die Methode ist dabei in Bezug auf die Anzahl der übergebenen Parameter flexibel. Das heißt, es muss zwar mindestens ein Element angegeben werden, es können aber auch zwölf sein.

Das folgende Beispiel erzeugt wieder ein Array mit den Monatsnamen, aber in mehreren Schritten:

var monate = new Array("Januar", "Februar", "März");
monate.push("April", "Mai", "Juni", "Juli", "August");
monate.push("September", "Oktober", "November",
   "Dezember");

Natürlich ist es auch möglich, Elemente aus einem Array zu entfernen. An die Methode push() ist die Methode pop() angelehnt, die das letzte Element aus einem Array entfernt. Viel flexibler ist jedoch die Methode splice(), die Elemente aus einem Array entfernt (diese Methode fehlt übrigens im Internet Explorer). Dieser Methode werden mindestens zwei Parameter übergeben:

gpBilder
 
Der erste Parameter gibt an, ab welcher Position Elemente entfernt werden sollen (wie immer beginnt die Zählung bei null).
gpBilder
 
Der zweite Parameter enthält die Anzahl der Array-Elemente, die aus dem Array entfernt werden sollen.
gpBilder
 
Alle folgenden Parameter werden wie bei push() hinten an das Array angefügt. Diese Parameter sind jedoch optional, es ist also auch möglich, aus einem Array nur Elemente zu entfernen.

Im folgenden Beispiel enthält die Monatsliste einige Fehler, die mit einem einzigen Aufruf von splice() behoben werden:

var a = new Array("Januar", "Februar", "März", "April", "Mai", 
"JavaScript", "JScript", "Juni", "Juli", "August", "September");
//Aufgabe: die Einträge an Position 5 und 6 entfernen
//und die fehlenden Einträge/Monate anhängen
a.splice(5, 2, "Oktober", "November", "Dezember");


13.1.3 Array-Elemente mischen  

Als Anwendungsbeispiel für Arrays wird ein Kartenblatt verwaltet; jedes Array-Element ist eine Karte, die allerdings selbst wieder ein Array ist (mit Kartenname und Kartenfarbe). Zum Mischen der Karten wird ein neues Array erstellt. Ein Element aus dem Array mit den Karten wird zufällig ausgewählt und an ein neues Array angehängt. Abschließend muss die Karte noch aus dem alten Array entfernt werden, damit sie im neuen Array nicht etwa doppelt vorkommt. Der folgende Code ist somit ziemlich selbsterklärend. In Kapitel 24 finden Sie einen ähnlichen Code noch einmal.

//Hilfsvariablen für die Kartenbezeichnungen
var kartenname = new Array();
kartenname[0]="Zwei"; kartenname[1]="Drei";
kartenname[2]="Vier"; kartenname[3]="Fünf";
kartenname[4]="Sechs"; kartenname[5]="Sieben";
kartenname[6]="Acht"; kartenname[7]="Neun";
kartenname[8]="Zehn"; kartenname[9]="Bube";
kartenname[10]="Dame"; kartenname[11]="König";
kartenname[12]="As";
var farben = new Array();
farben[0] = "Herz"; farben[1] = "Karo";
farben[2] = "Pik"; farben[3] = "Kreuz";
//Initialisierung des Karten-Arrays
var cards = new Array();
for (var i=0; i<13; i++)
   for (var j=0; j<4; j++){
      karte = kartenname[j] + " " + farben[i];
      cards.push(karte);
   }
//Mischen
var neu = new Array();
while (cards.length > 0){
   var zufall = Math.floor(Math.random() * cards.length);
   karte = cards[zufall];
   cards.splice(zufall, 1);
   neu.push(karte);
}


13.1.4 Sortieren 
topBilder

In JavaScript gibt es die Methode sort() für Arrays, die die Elemente eines Arrays alphanumerisch sortiert. Zuvor werden die Array-Elemente alle in Zeichenketten umgewandelt, was zu Problemen führt:

var a = new Array(1, 3, 5, 7, 11).sort();

Nach diesem Aufruf hat a den Wert [1, 11, 3, 5, 7], denn sowohl eins als auch elf beginnen mit einer "1" – und das kommt im ASCII-Alphabet vor der "3". Man kann sich hier jedoch behelfen, indem man eine Sortierfunktion schreibt. Das muss eine Funktion sein, der zwei Parameter übergeben werden können. Diese Funktion gibt dann eine positive Zahl zurück, wenn der erste Parameter gemäß den Sortierkriterien »größer« als der zweite Parameter ist; ist der zweite Parameter der »größere«, wird eine negative Zahl zurückgegeben. Im dritten Fall, wenn die beiden Parameter »gleich groß« sind, muss der Rückgabewert der Funktion 0 betragen.

In unserem Beispiel soll das Kartenblatt sortiert werden, und zwar nach dem Wert der Karten. Hierbei wird folgendermaßen vorgegangen:

gpBilder
 
Alle Zeichen vor dem Leerzeichen stellen die eigentliche Karte dar (also ohne Farbwert).
gpBilder
 
In einem Array sind die Kartenwerte abgespeichert.
gpBilder
 
Von den beiden übergebenen Parametern wird der Array-Index im Kartenwert-Array ermittelt. So kann angegeben werden, welche Karte »größer« ist und welche »kleiner«. Dementsprechend kann der korrekte Wert zurückgegeben werden.
gpBilder
 
Haben beide Karten denselben Wert, so wird (alphabetisch) nach der Farbe sortiert.

Die folgende Funktion erledigt das und verwendet eine praktische JavaScript-Methode: Zeichenkette.split(Trennzeichen). Die Zeichenkette wird anhand der Trennzeichen aufgeteilt, und die einzelnen Teilstrings werden in einem Array zurückgegeben. Der Aufruf

"1;2;3".split(";");

liefert folgendes Array zurück:

[1, 2, 3]

Nun aber zur Sortierfunktion:

function cardsort(a, b) {
   var kartenname = new Array();
   kartenname[0]="Zwei"; kartenname[1]="Drei";
   kartenname[2]="Vier"; kartenname[3]="Fünf";
   kartenname[4]="Sechs"; kartenname[5]="Sieben";
   kartenname[6]="Acht"; kartenname[7]="Neun";
   kartenname[8]="Zehn"; kartenname[9]="Bube";
   kartenname[10]="Dame"; kartenname[11]="König";
   kartenname[12]="As";
   var wert_a = (a.split(" "))[0];
   var wert_b = (b.split(" "))[0];
   var index_a = –1; var index_b = –1;
   for (var i=0; i<kartenname.length; i++) {
      if (kartenname[i] == wert_a) {
         index_a = i;
      }
      if (kartenname[i] == wert_b) {
         index_b = i;
      }
   }
   if (index_a > index_b) {
      return 1;
   } else if (index_a < index_b) {
      return –1;
   }
   var farbe_a = (a.split(" "))[1];
   var farbe_b = (b.split(" "))[1];
   return (farbe_a > farbe_b) ? 1 : 0;
}

Der Name der Funktion wird dann als Parameter an die sort()-Methode des Arrays übergeben. Beachten Sie, dass hierbei dem Funktionsnamen keine Klammern folgen.

//Hilfsvariablen für die Kartenbezeichnungen
var kartenname = new Array();
kartenname[0]="Zwei"; kartenname[1]="Drei";
kartenname[2]="Vier"; kartenname[3]="Fünf";
kartenname[4]="Sechs"; kartenname[5]="Sieben";
kartenname[6]="Acht"; kartenname[7]="Neun";
kartenname[8]="Zehn"; kartenname[9]="Bube";
kartenname[10]="Dame"; kartenname[11]="König";
kartenname[12]="As";
var farben = new Array();
farben[0] = "Herz"; farben[1] = "Karo";
farben[2] = "Pik"; farben[3] = "Kreuz";
//Initialisierung des Karten-Arrays
var cards = new Array();
for (var i=0; i<13; i++) {
   for (var j=0; j<4; j++){
      karte = kartenname[i] + " " + farben[j];
      cards.push(karte);
   }
}
//Mischen
var neu = new Array();

while (cards.length>0) {
   var zufall = Math.floor(Math.random()*cards.length);
   karte = cards[zufall];
   cards.splice(zufall, 1);
   neu.push(karte);
}
//Sortieren
neu.sort(cardsort);
//Hand ausgeben
document.write(neu.toString());

Mit der Methode toString() wird jedes Objekt, sofern möglich, in eine Zeichenkette umgewandelt. Bei einem Array in JavaScript werden die einzelnen Elemente durch Kommata getrennt ausgegeben.

Beachten Sie, dass in Abbildung 13.1 das Kartenblatt sortiert ist. Wenn Sie im Listing die Zeile neu.sort(cardsort) auskommentieren, erhalten Sie ein vermischtes Blatt (siehe Abbildung 13.2).

Bilder

Abbildung 13.1     Das gemischte und dann wieder sortierte Array

Bilder

Abbildung 13.2     Das unsortierte Array

 

 

13.2 Eigene Objekte 
topBilder

In diesem Abschnitt sollen einige Array-Funktionalitäten der aktuellen JavaScript-Version 1.2 für ältere Browser (und die meisten Versionen des Internet Explorer) nachgebildet werden. Dazu ist es nötig, eigene Objekte zu erstellen.

In der Praxis wird diese Technik nur bei größeren Projekten verwendet und in solchen Fällen, in denen der Funktionsumfang der üblichen Variablen und Arrays nicht mehr ausreicht.


13.2.1 Allgemeines  

In ganz alten JavaScript-Versionen (und -Browsern) war es üblich, mit der folgenden Hilfsfunktion Arrays zu erstellen:

function MakeArray(n) {
   for (var i=0; i<n; i++) {
      this[i] = 0;
   }
   this.length = n;
}

Hier die kurze Erklärung für den obigen Code: Mit dem Schlüsselwort this wird ja normalerweise auf das aktuelle Objekt zugegriffen, im Allgemeinen auf das aktuelle Fenster oder Formularelement. Wird diese Funktion jedoch als so genannte Konstruktorfunktion für ein Objekt verwendet, also mit new MakeArray() aufgerufen, so bezeichnet this die aktuelle Instanz des Objekts. Somit wird durch die wiederholte Ausführung des Befehls this[i]=0 die Instanz als Array deklariert und jedes Array-Element mit null vorbelegt. Von besonderer Bedeutung ist die Zeile this.length = n. Hierdurch wird die Eigenschaft length des Objekts auf n gesetzt und nicht etwa die Länge eines Arrays (Anzahl der Elemente) festgelegt. Standardmäßig hat ja ein Array unbegrenzt viele Elemente, und das ist auch hier so. Da es sich hierbei aber um kein »echtes« Array handelt, sondern um ein eigenes Objekt, hat die Eigenschaft length nichts mit der Anzahl der Elemente des Objekts zu tun. Wird also ein Element an das Array angefügt, so wird length nicht automatisch angepasst; das muss man also selbst übernehmen. Aus diesem Grund sollten Sie bei der Implementierung für zusätzliche Funktionalität von MakeArray() sehr vorsichtig sein.


13.2.2 Methoden definieren  

Fast genauso einfach wie die Definition von Objekteigenschaften ist die Definition von Objektmethoden. Auch hier ist der this-Operator wieder von Bedeutung. Beim Setzen einer Methode verwendet man folgende Syntax im Konstruktor:

this.methode = funktion;

Bei jedem Aufruf der Methode wird funktion() ausgeführt, und innerhalb von funktion() kann man mit this auf die verwendete Instanz des Objekts zugreifen. Beachten Sie, dass auch hier die Klammern fehlen – denn funktion ist eine Referenz auf die Funktion funktion(). Und natürlich würden auch hier wieder anonyme Funktionen in Frage kommen.

Als Beispiel soll die Methode toString() implementiert werden. Dazu muss zunächst MakeArray() folgendermaßen geändert werden:

function MakeArray(n) {
   for (var i=0; i<n; i++) {
      this[i] = 0;
   }
   this.length = n;
   this.toString = arraytoString;
}

Die Funktion arraytoString() gibt die Elemente des Arrays, durch Kommata voneinander getrennt, aus. Dazu werden einfach alle Elemente in this abgefragt und miteinander verkettet.

function arraytoString() {
   var returnstring = "";
   for (var i=0; i<this.length-1; i++) {
      returnstring += this[i] + ",";
   }
   returnstring += this[this.length-1];
   return returnstring;
}

Analog kann man auch die Funktion push() nachbilden: Alle übergebenen Parameter werden an das Array angehängt. Abschließend muss die Eigenschaft length noch angepasst werden.

function MakeArray(n) {
   for (var i=0; i<n; i++) {
      this[i] = 0;
   }
   this.length = n;
   this.toString = arraytoString;
   this.push = arraypush;
}
function arraypush() {
   for (var i=0; i<arraypush.arguments.length; i++) {
      this[this.length+i] = arraypush.arguments[i];
   }
   this.length += arraypush.arguments.length;
}


13.2.3 Eigene Sortiermethode  

Das Sortieren war bei JavaScript Version 1.0 noch nicht möglich. Erstellt man jedoch ein eigenes Objekt, kann man diese Funktionalität auch nachbilden. Die Einrichtung einer Methode ist nicht schwer, Sie müssen nur eine Zeile in die Konstruktorfunktion einfügen:

function MakeArray(n) {
   for (var i=0; i<n; i++) {
      this[i] = 0;
   }
   this.length = n;
   this.toString = arraytoString;
   this.push = arraypush;
   this.sort = arraysort;
}

Bei der Implementierung der Funktion arraysort() muss man sich zunächst für einen geeigneten Sortieralgorithmus entscheiden. Am leichtesten tut man sich – zumindest meiner Meinung nach – mit dem Bubblesort-Algorithmus. Der benötigt zwar eine quadratische Laufzeit (unter diesem Aspekt gibt es bessere Algorithmen), aber er ist dafür besonders einfach zu implementieren. Das Verfahren funktioniert wie folgt: Zwei nebeneinanderliegende Elemente des Arrays werden miteinander verglichen. Haben diese Elemente schon die richtige Reihenfolge (ist das »linke« also kleiner als das »rechte«), passiert nichts, ansonsten tauschen die beiden Elemente ihren Platz. Sodann werden das jetzt rechts liegende Element und das Element rechts daneben betrachtet. Auf diese Weise wird das gesamte Array durchlaufen, und das geschieht so oft, bis das Array korrekt sortiert ist.

Das folgende Ablaufschema zeigt exemplarisch die Sortierung. Elemente, die vertauscht werden, sind jeweils unterstrichen:

3142®1342®1324®1234

Zunächst muss man sich überlegen, wie man zwei Elemente – oder vereinfacht gesagt, zwei Variablen – vertauscht. Der folgende Code funktioniert leider nicht:

var a, b;
function tausche(){
   a = b;
   b = a;
}

Nachdem die Zuweisung a = b ausgeführt worden ist, enthalten a und b denselben Wert; der ursprüngliche Wert von a ist verloren. Um nun wirklich vertauschen zu können, verwendet man eine Hilfsvariable, in der man den ursprünglichen Wert von a abspeichert. Dann wird a der Wert von b zugewiesen, und b erhält den ursprünglichen Wert von a – aus der Hilfsvariablen:

var a, b;
function tausche() {
   var hilfsvariable = a;
   a = b;
   b = hilfsvariable;
}

Die Implementierung des Bubblesort-Algorithmus ist dann nicht weiter schwierig. Man darf sich nur beim Vertauschen der Array-Elemente nicht vertun und muss immer fleißig this verwenden!

function arraysort() {
   var sortiert = false;  //Überprüfung, ob sortiert
   while (!sortiert) {
      sortiert = true;
      for (var i = 0; i < this.length – 1; i++) {
         if (this[i] > this[i+1]) {
            sortiert = false;
            hilfsvariable = this[i];
            this[i] = this[i+1];
            this[i+1] = hilfsvariable;
         }
      }
   }
}

Beachten Sie, dass die Variable i von 0 bis this.length-2 läuft, da das Array-Element an der Position i mit dem nachfolgenden Element verglichen wird – und das Element an der Position this.length-1 hat keinen Nachfolger.


13.2.4 Eigene Sortiermethode, Teil 2  

In Hinblick auf das Beispiel mit dem Kartenspiel wäre es natürlich noch schön, wenn man wieder die Sortiermethode selbst angeben könnte. Auch dies kann man mit JavaScript erreichen. Zunächst muss man die Funktion arraysort() leicht modifizieren:

function arraysort() {
   var sortiert = false;  //Überprüfung, ob sortiert
   while (!sortiert) {
      sortiert = true;
      for (var i=0; i<this.length-1; i++) {
         if (groesser(this[i], this[i+1],
            arraysort.arguments[0])){
            sortiert = false;
            hilfsvariable = this[i];
            this[i] = this[i+1];
            this[i+1] = hilfsvariable;
         }
      }
   }
}

Die Funktion groesser(a, b, arg) gibt zurück, ob a größer als b ist; arg enthält einen an die Funktion arraysort() übergebenen Parameter (wozu der nützlich ist, wird gleich erläutert). Im Beispiel aus dem vorigen Abschnitt würde diese Funktion folgendermaßen aussehen:

function groesser(a, b, arg) {
   return (a > b);
}

Unser Ziel soll es jedoch sein, eine beliebige Funktion an arraysort() bzw. an die Methode sort() des MakeArray-Objekts zu übergeben. Aufgrund der Einschränkungen von JavaScript muss der Name der Sortierfunktion als Zeichenkette übergeben werden. Der Rest ist dann gar nicht mehr so schwierig. Mittels eval() wird die Sortierfunktion mit zwei Array-Elementen als Parametern aufgerufen und das Ergebnis ausgewertet. Zur Erinnerung: Nur wenn das Ergebnis größer als 0 ist, ist der erste Parameter größer als der zweite. Zusätzlich muss natürlich noch überprüft werden, ob überhaupt ein Parameter an arraysort() übergeben worden ist. Sollte das nicht der Fall sein, wird ein alphanumerischer Vergleich mit dem >-Operator durchgeführt.

function groesser(a, b, arg) {
   if (arg == null) {
      return (a>b);
   } else {
      var erg = eval(arg + "("" + a + "", "" + b +
      "")");
      return (erg > 0);
   }
}


13.2.5 Zusammenfassung  

Im Folgenden finden Sie eine Anwendung für das MakeArray-Objekt. Das Kartenblatt wird initialisiert, in vier Teile aufgeteilt (beispielsweise für eine Partie Schafkopf zu viert) und (sortiert) ausgegeben.

Die Funktion MakeArray() (beziehungsweise, um exakt zu sein: der Klassenkonstruktor – derjenige Code, der bei der Instanziierung der Klasse aufgerufen wird) wurde für dieses Beispiel leicht angepasst, so dass man als Parameter nicht die Größe des Arrays übergibt, sondern die anfänglichen Array-Elemente selbst.

<html>
<head>
<title>Karten spielen mit JavaScript</title>
<script type="text/javascript"><!--
//Funktionen des MakeArray-Objekts
function MakeArray(){
   for (var i = 0; i < MakeArray.arguments.length; i++) {
      this[i] = MakeArray.arguments[i];
   }
   this.length = MakeArray.arguments.length;
   this.toString = arraytoString;
   this.push = arraypush;
   this.sort = arraysort;
}
//Methoden
function arraytoString() {
   var returnstring = "";
   for (var i=0; i<this.length-1; i++) {
      returnstring += this[i] + ",";
   }
   returnstring += this[this.length-1];
   return returnstring;
}
function arraypush() {
   for (var i=0; i<arraypush.arguments.length; i++) {
      this[this.length+i] = arraypush.arguments[i];
   }
   this.length += arraypush.arguments.length;
}
function arraysort() {
   var sortiert = false;  //Überprüfung, ob sortiert
   while (!sortiert) {
      sortiert = true;
      for (var i=0; i<this.length-1; i++) {
         if (groesser(this[i], this[i+1],
            arraysort.arguments[0])) {
            sortiert = false;
            hilfsvariable = this[i];

            this[i] = this[i+1];
            this[i+1] = hilfsvariable;
         }
      }
   }
}
function groesser(a, b, arg) {
   if (!arg) {
      return (a>b);
   } else {
      var erg = eval(arg + "("" + a + "", "" + b +
      "")");
      return (erg > 0);
   }
}
// *** Das eigentliche Programm ***
//Hilfsvariablen für die Kartenbezeichnungen var kartenname = new MakeArray("Zwei", "Drei", "Vier", "Fünf", "Sechs", "Sieben", "Acht", "Neun", "Zehn", "Bube", "Dame", "König", "As"); var farben = new MakeArray("Herz", "Karo", "Pik", "Kreuz"); //Initialisierung des Kartenarrays var cards = new MakeArray(); for (var i=0; i<13; i++) { for (var j=0; j<4; j++) { karte = kartenname[i] + " " + farben[j]; cards.push(karte); } } //Karten mischen //Karten auf vier Personen verteilen var hand1 = new MakeArray(); var hand2 = new MakeArray(); var hand3 = new MakeArray(); var hand4 = new MakeArray(); for (i=0; i<=12; i++) { hand1.push(cards[i]); } for (i=13; i<=25; i++) { hand2.push(cards[i]); } for (i=26; i<=38; i++) { hand3.push(cards[i]); } for (i=39; i<=51; i++) { hand4.push(cards[i]); } //Karten sortieren hand1.sort("cardsort"); hand2.sort("cardsort"); hand3.sort("cardsort"); hand4.sort("cardsort"); //Sortierfunktion function cardsort(a, b) { var wert_a = a.substring(0, a.indexOf(" ")); var wert_b = b.substring(0, b.indexOf(" ")); var index_a = –1; var index_b = –1; for (var i=0; i<kartenname.length; i++) { if (kartenname[i] == wert_a) { index_a = i; } if (kartenname[i] == wert_b) { index_b = i; } } if (index_a > index_b) { return 1; } else if (index_a < index_b) { return –1; } var farbe_a = a.substring(a.indexOf(" ")+1, a.length); var farbe_b = b.substring(b.indexOf(" ") + 1, b.length); return (farbe_a > farbe_b) ? 1 : 0; } //--></script> </head> <body> <h1>Karten spielen mit JavaScript</h1> <script type="text/javascript"><!-- function br() { return "<" + "br" + " />"; } document.write("Hand 1: " + hand1.toString() + br()); document.write("Hand 2: " + hand2.toString() + br()); document.write("Hand 3: " + hand3.toString() + br()); document.write("Hand 4: " + hand4.toString() + br()); //--></script> </body> </html>

Bilder

Abbildung 13.3     Die an vier Leute verteilten Karten, sortiert


13.2.6 Platzsparende Notation 
topBilder

Auch bei Objekten gibt es – ähnlich wie bei Arrays – eine platzsparende Notation. Hier ein Beispiel für das handgeschriebene Array, zwar ohne Funktionalität im Konstruktor, aber mit einigen Methoden:

var a = {
   "length": 0,
   "toString": function () {
      var returnstring = "";
      for (var i=0; i<this.length-1; i++) {
         returnstring += this[i] + ",";
      }
      returnstring += this[this.length-1];
      return returnstring;
   },
   "push": function() {
      for (var i=0; i<arraypush.arguments.length; i++) {
         this[this.length+i] = arraypush.arguments[i];
      }
      this.length += arraypush.arguments.length;
   }
};

Sie sehen also: Mit den geschweiften Klammern zeigen Sie an, dass ein Objekt vorliegt. Eigenschaften (oder Methoden) und ihre Werte (oder Implementierungen werden durch Doppelpunkte voneinander getrennt. Auch diese Kurznotation werden Sie an späterer Stelle wiederfinden: in Kapitel 18 unter dem Namen »JSON«.

 

 

13.3 JavaScript-Objekte erweitern 
topBilder
topBilder

Eine besondere Eigenschaft jeder JavaScript-Klasse ist prototype. Damit können Sie unter anderem das OOP-Konzept der Vererbung implementieren. Als Wert für die Eigenschaft prototype geben Sie Eigenschaften und Methoden an, die alle Objekte der Klasse haben sollen. Angenommen, Sie haben eine allgemeine Klasse Auto implementiert, mit Eigenschaften wie ps und Methoden wie beschleunigen(). Dann erstellen Sie eine Klasse ElchAuto. Die soll alle Eigenschaften und Methoden der Klasse Auto besitzen, allerdings auch eine neue Methode: umkippen(). Das machen Sie dann so:

function Auto() {
  // Auto wird implementiert ...
}

function ElchAuto() {
   this.umkippen = function() {
      // umkippen implementieren
   };
}
ElchAuto.prototype = new Auto();

Diese Form der Erweiterung ist allerdings auch bei bestehenden JavaScript-Objekten möglich! Erinnern Sie sich noch an die Funktion zufall_intervall()aus Kapitel 6? Wenn diese einen Wert zwischen 65 und 90 zurückliefert, liegt ein ASCII-Code eines zufälligen Zeichens zwischen A und Z vor. Es wäre doch schön, wenn das String-Objekt von JavaScript eine solche Funktionalität direkt als Methode anbieten würde (zugegeben, über den praktischen Nutzen kann man diskutieren, aber es geht vor allem ums Prinzip). Mit der prototype-Eigenschaft ist das kein Problem:

function zufall_intervall(a, b) {
  var z = Math.random();
  z *= (b – a + 1);
  z += a;
  return (Math.floor(z));
}

String.prototype.random = function() {
return String.fromCharCode(zufall_intervall(65, 90));
};

Das String-Objekt besitzt jetzt eine Methode random(), allerdings nur wenn Sie die Klasse instanziieren (oder einen neuen String erstellen). Hier sehen Sie ein komplettes Beispiel, das ein Zufallszeichen zwischen A und Z erzeugt und ausgibt:

<html>
<head>
<title>Events</title>
<script type="text/javascript"><!--
function zufall_intervall(a, b) {
   var z = Math.random();
   z *= (b – a + 1);
   z += a;
   return (Math.floor(z));
}
String.prototype.random = function() {
   return String.fromCharCode(zufall_intervall(65, 90));
};
//--></script>
</head>
<body>
<h1>Event-Listener</h1>
<form>
<input type="button" value="Zufallszeichen"
   onclick="alert((new String()).random());" />
</body>
</html>

Bilder

Abbildung 13.4     Ein zufälliges Zeichen

Das Tutorial ist ein Auszug aus der 7. Auflage des Buches von Christian Wenz:

JavaScript und Ajax - Das umfassende Handbuch
Galileo Computing, 853 Seiten, 8. aktualisierte Auflage

Die Veröffentlichung des Kapitels erfolgt mit freundlicher Genehmigung von Galileo Press.

Mehr Informationen zum aktualisierten Fachbuch für Webentwickler gibt es hier: JavaScript und Ajax
 
Alle Kapitel des Buches:
1 Grundlagen
2 JavaScript-Praxis
3 Professionelles JavaScript
4 Web 2.0 und Ajax
5 Kommunikation
6 Serverseitige Programmierung
7 Sicherheit
8 Praxis
9 Anhang
Bilder


 

DVD-Werbung
Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von tanzfrosch
  • 11.01.2018 - 14:55

Dankeschön, tolles Tut. !

x
×
×