In der Welt des Computers gibt es nur Daten. Was nicht Daten ist, ist nicht. Programme sind Daten. Programmen erschaffen neue Daten. Es ist ein eigenartiger, auf Silikon basierender Kreislauf des Lebens.
Lerne mehrere Werte in einer Datenstruktur zu gruppieren und diese Gruppierung zu verwenden.
Aufgabe: Zeichne einen Regenbogen indem du sieben konzentrische Kreise mit den Farben red, orange, yellow, green, cyan, purple, white zeichnest, wobei jeder Kreis kleiner als der zuvor ist.
Das ist der naive Ansatz:
function rainbow(x, y) { color("red"); circle(x, y, 150); color("orange"); circle(x, y, 145); color("yellow"); circle(x, y, 140); color("green"); circle(x, y, 135); color("cyan"); circle(x, y, 130); color("purple"); circle(x, y, 125); color("white"); circle(x, y, 120); }
Das ist nicht falsch, aber es ist einfach nicht richtig. Es ist voller Wiederholungen. Hier ist eine bessere Variante:
function rainbow(x, y) { var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"]; var count = 0; while (count < colors.length) { color(colors[count]); circle(x, y, 150 - 5 * count); count = count + 1; } }
Das Ding mit den eckigen Klammern ([ und ]) wird ein Array genannt. Ein Array ist ein Wert der andere Werte enthält - in diesem Fall enthält er sieben Strings die Farben benennen.
Die Werte in einem Array werden seine Elemente genannt. Die
Elemente in einem Array sind geordnet, was bedeutet, dass jedes Element
eine Position innerhalb des Arrays hat. Die Positionen in einem Array
werden ab Null gezählt, so dass im Beispiel oben "red"
die
Position 0 hat, und "white"
(das siebte Element) die
Position 6. Die Schreibweise colors[1]
wird benutzt, um auf
die Elemente in einem Array zuzugreifen — in diesem Fall wäre es
"orange"
.
Eine weitere neue Schreibweise ist der Punkt in
colors.length
, auch wenn wir den bei
Math.random
schon gesehen haben.
Er wird verwendet, um auf andere Arten von Werten zuzugreifen, die
Eigenschaften (properties) genannt werden. Bei
Math.random
wird es nur zur Gruppierung verwendet:
Eine ganze Sammlung von mathematischen Funktionen sind als Eigenschaften
von Math
verfügbar (zum Beispiel Math.round
zum Runden von Zahlen). Aber im Fall von colors.length
wird auf eine Eigenschaft zugegriffen, die in direkter Verbindung zum
Array colors
steht: die Gesamtzahl der Elemente im Array
(sieben).
Die while
-Schleife läuft eines nach dem anderen über die
Elemente des Arrays und verwendet dabei die Variable count
,
um ihre Position zu speichern. Bei jedem Schritt werden die Elemente
benutzt, um die aktuelle Farbe zu setzen und anschließend wird ein Kreis
der passenden Größe gezeichnet.
Weil diese Art von Schleife (Variable erzeugen, in der
while
-Bedingung prüfen, und aktualisieren) sehr häufig
vorkommt, gibt es eine kompaktere Schreibweise dafür. Dieses Programm
ist äquivalent zu dem vorherigen:
function rainbow(x, y) { var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"]; for (var count = 0; count < colors.length; count = count + 1) { color(colors[count]); circle(x, y, 150 - 5 * count); } }
In einer for
-Schleife werden das Initialisieren der
Variablen der Schleife, das Prüfen der Bedingung, und das Aktualisieren
der Werte zusammen gruppiert, damit einfacher gesehen werden kann, dass
sie gemeinsam die Schleife ausmachen.
Lerne Objekte zu erzeugen und auf ihre Eigenschaften zuzugreifen.
Öffne die Konsole wieder, falls du sie geschlossen hast.
Erzeuge eine Variable indem du folgendes in die Konsole eingibst:
var myObject = {name: "Larry", score: 100};
Führe myObject.name
und myObject.score
aus.
Führe zudem myObject["name"]
und myObject["sco" +
"re"]
aus.
Gib dem Objekt mit myObject.color =
"purple"
eine Eigenschaft hinzu. Dann führe
myObject.color
aus.
Verändere die score
-Eigenschaft mit
myObject.score = 105
. Führe dann wieder myObject.score
aus, um sicher zu gehen, dass es geklappt hat.
Objekte sind ebenfalls Gruppierungen von Werten. Sie verlangen aber, dass jeder Wert einen Namen hat. Arrays sind nützlich, um irgendeine Menge von Werten in einer homogenen Gruppe zu sammeln. Objekte dagegen sind besser geeignet wenn jeder Wert eine klar bestimmte Rolle in der Gruppierung spielt. Zum Beispiel ist eine Tüte Chips ein Array, aber die Teile eines Autos (Motor, Räder, etc.) bilden ein Objekt.
Die Schreibweise {property1: value1, property2: value2}
wird verwendet, um ein Objekt zu erzeugen. Es gibt zwei Arten um auf die
Eigenschaften eines Objektes zuzugreifen. Die Art mit Punkt,
object.property
, wird verwendet, wenn der Name der
Eigenschaft schon beim Schreiben des Programms bekannt ist.
Die Art mit Klammern, object["property"]
, lässt zu, dass
der Name der Eigenschaft als beliebiger Ausdruck angegeben wird und ist
daher nützlich, wenn der Name erst noch erstellt werden muss.
Zusammen bieten Objekte und Arrays die Möglichkeit, eine große Bandbreite an Informationen darzustellen. Ein Beispiel: Eine Liste von Spielern in einem Spiel würde üblicherweise ein Array von Objekten sein, worin jedes Objekt einen Spieler repräsentiert. Falls eine Liste von Ergebnissen mit einzelnen Spielern verbunden wird, wäre diese wiederum ein Array in jedem der Spieler-Objekte. So kann man beliebig fortfahren.
Übung: Überlege dir eine JavaScript-Repräsentierung eines Schachbretts. Es gibt mehrere gute Lösungen.
Mache eine einfache Visualisierung eines Datensatzes
In unserer Spielumgebung haben wir eine neue Variable zur Verfügung,
countryData
. Sie enthält ein Array von Objekten mit
Informationen (Bevölkerung, Lebenserwartung) über die meisten Länder der
Erde.
Jedes Objekt stellt ein Land dar und enthält eine
name
-Eigenschaft mit einem String, sowie
population
- und
life_expectancy
-Eigenschaften die Arrays mit Zahlen
enthalten. Diese Zahlen geben die Werte der entsprechenden Statisiken
(Bevölkerungszahl und Lebenserwartung in Jahren) für die Jahre 1960 bis
2011 an.
Dieses Programm wählt ein paar Länder aus und stellt den Trend ihrer jeweiligen Lebenserwartung für den verfügbaren Zeitraum als Punktdiagramm dar.
var width = 600, height = 300; function showCountry(country) { var step = width / country.life_expectancy.length; for (var pos = 0; pos < country.life_expectancy.length; pos = pos + 1) { var le = country.life_expectancy[pos]; circle(step * pos, le * height / 100, 2); } } function drawing() { moveTo(-width / 2, -height / 2); color("red"); showCountry(countryData[66]); // Germany color("green"); showCountry(countryData[81]); // India color("blue"); showCountry(countryData[150]); // Russian Federation }
Du kannst es hier in Aktion sehen.
Um die Zeichnung mit ein wenig Disziplin zu erstellen, definiert das Programm zunächst die Breite und Höhe des Bereichs in den gezeichnet werden soll. 600 auf 300 Einheiten.
Die Funktion showCountry
nimmt ein Land-Objekt als
Parameter und läuft in einer Schleife über alle Lebenserwartungs-Werte
dieses Landes. Es berechnet den horizontalen Abstand den es zwischen
Punkten lassen will und speichert ihn in der Variable step
.
Unter der Annahme, dass die Lebenserwartung stets zwischen 0 und 100 Jahren
liegen wird, teilt es die Höhe des Zeichenbereichs durch 100, um die Zahl
der Einheiten zu bestimmen, die ein Jahr Lebenserwartung darstellen.
Die Funktion drawing
bewegt zuerst das Koordinatensystem
so, dass (0,0) die linke untere Ecke des Zeichenbereichs und damit des
Graphen ist. Es ruft dann showCountry
auf drei
verschiedenen Ländern auf, wobei es jedem eine andere Farbe gibt.
Übung: Die Position eines Landes in der Sammlung
kennen zu müssen, um es anzeigen zu können, ist irgendwie unpraktisch.
Schreibe eine Funktion findCountry
, die einen String mit
einem Ländernamen als Parameter nimmt, durch das Array countryData
läuft und das Objekt für das genannte Land zurück gibt.
Um das tun zu können, musst du wissen, dass das Stichwort
return
benutzt werden kann, um eine Anweisung zu schreiben,
die einen Wert an die Stelle im Code zurück gibt, die die Funktion
aufgerufen hat. Zum Beispiel:
function timesThree(x) { return x * 3; } console.log(timesThree(3)); // Logs 9
Übung: Ein großes Problem mit unseren Graphen ist,
dass man gar nicht erkennen kann, wofür die Punkte eigentlich stehen.
Schreibe zusätzlichen Code der graue horizontale Linien zeichnet (mit
der Funktion line(x1, y1, x2, y2)
), sodass hinter dem
Graph zu sehen ist, wo 10, 20, ..., usw. bis 100 Jahre Lebenserwartung
liegen. Benutze die Variablen width
und height
,
um die Linien richtig zu platzieren.
Wenn du magst, kannst du auch noch Beschriftungen mit der Funktion
text(x, y, string)
hinzufügen oder eine Skala für den
Zeitraum zeichnen lassen.
Übrung: Passe die Funktion showCountry
so an, dass sie eine durchgehene Linie statt einer Folge von Punkten
zeichnet..
Schreib auf eigene Faust ein Programm, dass einen Datensatz zusammen fasst.
Im Programm für diesen
Schritt, gibt es die Funktion visualizeHistory
,
die der zuvor genutzten Funktion showCountry
sehr ähnlich ist, die aber einen Graphen für beliebige Daten zeichnen
kann. Sie nimmt als Parameter ein Array mit Zahlen und eine vertikale
Einheit entgegen. Die vertikale Einheit gibt an, wieviel vertikalen Raum
eine Einheit des Zahlen-Arrays einnimmt.
Vervollständige die Funktion showWorldPopulation
. Sie
soll die Weltbevölkerung für jedes der Jahre im Datensatz berechnen,
die Ergebnisse in ein Array speichern und damit die Funktion
visualizeHistory
aufrufen.
Um ein Array aufzufüllen kannst du folgende Technik verwenden
var newArray = []; // empty for (var i = 0; i < 10; i = i + 1) { newArray.push(i); }
Die Funktion push
ist eine Eigenschaft
(Methode) jedes Arrays und fügt dem Array einen Wert hinzu.
Um die richtige vertikale Einheit für deinen Graph zu bestimmen,
musst du die maximale Weltbevölkerung, der dein Programm begegnet,
speichern. Das kannst du entweder mit if
und dem
>
-Operator tun, oder mit der Funktion
Math.max
, die zwei Zahlen als Parameter nimmt und die
größere der beiden zurück gibt.
Die Daten sind nicht im geeignetsten Format, um die Bevölkerung pro Jahr zusammen zu zählen. Dafür hätten wir lieber die Möglichkeit, eine Sammlung aller Bevölkerungszahlen eines Jahres direkt zu erhalten.
Trotzdem kommen wir an die Daten heran, indem wir eine Schleife in
einer Schleife verwenden, wobei die äußere Schleife über die Jahre läuft
(zum Beispiel mit countryData[0].population.length
als
Gesamtzahl des Zeitraums), und die innere Schleife über die Länder.
So kann die Bevölkerungszahl für das aktuelle Jahr aus jedem Land
geholt werden und zur Gesamtzahl für das Jahr addiert werden. Es ist
wichtig, dass der Zähler für die Gesamtzahl eines Jahres am Beginn der
äußeren Schleife zurück gesetzt wird.
Probier es aus! Falls du nicht weiterkommst, stelle einen Coach auf die Probe.
Einige andere Ideen, um interessante Darstellungen aus diesen Daten zu erschaffen:
region
-Eigenschaft. Das ist
eine dreistellige Abkürzung die die Welt in sieben Regionen aufteilt.
(Den vollen Namen kannst du mit der Funktion regionName
aus der Abkürzung erzeugen.) Versuch ein Diagramm zu zeichnen, dass
die Anteile der Weltbevölkerung zeigt, die in jeder dieser Regionen
leben, unterteilt nach Jahreszahlen. Zum Beispiel kannst du einen
vertikalen Stapel von farbigen Balken pro Jahr zeichnen.fertility
-Eigenschaft die für jedes Jahr die
Fruchtbarkeitsrate angibt.
Zeichne eine zweidimensionale Darstellung für jedes Jahr, die die
Korrelation zwischen Lebenserwartung und Fruchtbarkeitsrate zeigt,
d.h. Lebenserwartung auf der x-Achse, Fruchtbarkeit auf der
y-Achse.setTimeout
-Trick, der in
diesem Beispiel
aus der letzten Seite gezeigt wird. Schreite dazu jede
Zehntelsekunde zum nächsten Jahr fort und zeichne ein Bild für das
aktuelle Jahr. Mit einem Aufruf von text
kannst du das
aktuelle Jahr auch noch dazu schreiben.