4. Einen Webserver programmieren
4.1 Extrem kurze Einführung in Javascript
Um im Prinzip zu verstehen, wie Client (d.h. Ihr Browser) und Server (einer da draußen im Netz) interagieren, müssten Sie nicht unbedingt Javascript kennen. Da Sie es aber später für dynamische Webseiten eh brauchen, gebe ich Ihnen jetzt eine ganz kurze Einführung. Dann können Sie nämlich recht schnell auch Ihren eigenen Webserver schreiben. In der Praxis würde man natürlich viel mehr auf bestehende Produkte zurückgreifen, zum Lernen aber ist es gut, so viel wie möglich "per Hand" zu machen. Sehen Sie zu, dass auf Ihrem Rechner Node.js installiert ist. Node.js ist im Prinzip Javascript als alleinstehende Programmiersprache (im Gegensatz zu dem Javascript-Code, der vom Webbrowser ausgeführt wird). Node.js sollte an den Hochschulrechnern bereits installiert sein. Öffnen Sie ein Terminal und geben ein
node
Wenn das eine Fehlermeldung wie command not found
erzeugt, dann ist Node.js anscheinend noch nicht installiert. Installieren Sie es und
wenden Sie sich bei Problemen an Google, mich oder Ihre Kommilitonen.
Wenn es installiert ist, sollte sich ein Prompt öffnen, auf dem Sie, ähnlich wie z.B. in
Python oder DrRacket, direkt Ausdrücke und Code eingeben können:
Wir nennen diesen Prompt den REPL-Modus von Node. REPL steht für Read, Evaluate, Print, Loop. Da wir bald längeren Code schreiben werden (z.B. ganze Funktionen), und wir das nicht immer per Hand im REPL-Modus eingeben wollen, legen wir uns eine Datei mit Quelltext an. Am Besten legen Sie ein Verzeichnis javascript-examples an und in diesem eine Datei firstprogram.js. Öffnen Sie diese Datei (mit einem Editor Ihrer Wahl, zum Beispiel VS Code). Schreiben Sie in die Datei folgenden Beispielcode:node
Welcome to Node.js v16.13.1. Type ".help" for more information.1 + 1
2myArray = [1, 2, '3', 'vier', 5.0];
[ 1, 2, '3', 'vier', 5 ]myArray[3]
'vier'
Es gibt leider keine schöne Art und Weise, node anzuweisen, die Datei firstprogram.js zu lesen / auszuführen und dann in den REPL-Modus zu gehen (d.h. es gibt kein direktes Analog zufunction factorial(n) {
if (n == 0)
return 1;
else
return n * factorial(n-1);
}
python -i myProgram.py
).
Sie können aber einfach den Quelltext per Copy-Paste von firstprogram.js ins
REPL-Fenster kopieren. Starten Sie also nun Node.js auf dem Terminal:
node
und kopieren dann den Inhalt von firstprogram.js in das REPL-Fenster.
Testen Sie nun:
Der letzte Aufruf scheitert, weilfactorial(5)
120factorial(10)
3628800factorial(-1)
Uncaught RangeError: Maximum call stack size exceeded
factorial(-1)
in eine Endlosrekursion tritt.
while-Schleifen und if-Abfragen sind wie in Java.
Wichtig ist console.log(...)
, mit dem Sie beliebige Objekte
auf der Konsole ausdrucken lassen können. Es hat also eine ähnliche Rolle
wie System.err.println(...)
in Java.
Weitere wichtige Datentypen in Javascript sind:function collatz(n) {
while (n > 1) {
console.log(n);
if (n % 2 == 0) {
n = n/2;
}
else {
n = 3*n + 1;
}
}
}
-
Arrays, die Sie bereits
oben kennen gelernt haben:
myArray = [1,2,'3', 'vier']
- Strings
firstname = "dominik"
. Die können auch in Single-Quotes stehen:otherFirstname = 'dominik'
. Das ist nützlich, wenn Ihr String selbst Double-Quotes enthält:htmlTag = '<a href="index.html" class="styled-link">back to home</a>'
console.log(htmlTag)
<a href="index.html" class="styled-link">back to home</a>String htmlTag; htmlTag = "<a href=\"index.html\" class=\"styled-link\">back to home</a>"
-
Objekte. Oberflächlich gesehen, sind sie das Analog zum
struct
in C oder zu Klassen ohne Methoden in Java. Sie sind durch Schlüssel-Wert-Paare (key-value pairs) definiert:courseInstructor = {firstname: "Dominik", lastname: "Scheder"}
courseInstructor.firstname
'Dominik'courseInstructor.middlename
undefinedcourseInstructor.middlename = "Alban"
courseInstructor.middlename
'Alban'.
incourseInstructor.middlename
ist in gewisser Weise nur Augenwischerei. Man kann nämlich auch schreiben:courseInstructor["middlename"]
'Alban'java.util.Hashtable
oder einem dictionary in Python als einemstruct
in C. Sie können recht elegant durch ein Array oder die Eigenschaftenliste eines Objekts iterieren:array = [1, 2, 3, 4];
for (let x in array) {
console.log(x);
}
france = {
"capital": "Paris",
"continent": "Europe",
"currency": "Euro",
"population": 67897000
}
console.log(france.capital);
for (let key in france) {
console.log("The " + key + " of France is " + france[key]);
}
-
Funktionen. In Javascript sind Funktionen Werte, die
auch als Eingabewerte und Rückgabewerte für andere Funktionen
verwendet werden können. Davon wird in der Praxis
stark gebraucht gemacht. Als Beispiel wollen wir
eine Funktion schreiben, die ein Array unter einer
Operation "zusammenschmelzen" lässt. Zum Beispiel schmilzt
[1,2,3,4]
unter+
zu 10 zusammen, unter*
aber zu 24.function fold (array, neutralElement, combinatorFunction) {
let sum = neutralElement;
for (let i = 0; i < array.length; i++) {
sum = combinatorFunction (sum, array[i]);
}
return sum;
}
function add (x, y) {
return x + y;
}
fold([1,2,3,4], 0, add);
10fold(['1','2','3','4'], 0, add);
'01234'fold(['1','2','3','4'], '', add);
'1234'+
flexibel darauf reagiert, ob alle Argumente Zahlen sind oder ob ein String dabei ist. Nützlich istfold
zum Beispiel, wenn Sie eine Zeile in einem HTML<table>
erstellen wollen:tableHeaderArray = ["name", "capital", "continent", "currency", "population"]
result = fold(tableHeaderArray, '',
function (s1, s2) {
return s1 + "<th>" + s2 + "</th>";
}
);
'<th>name</th><th>capital</th><th>continent</th><th>currency</th><th>population</th>'combinatorFunction
implizit ohne Benennung definieren. Da wie sie wohl nur an dieser Stelle brauchen, lohnt es sich nicht, ihr einen Namen zu geben, und wir verwenden eine anonyme Funktion. Meiner Meinung erschwert das die Codeverständlichkeit; es wird aber in der Praxis stark davon Gebrauch gemacht.Ohne Probleme können Sie auch Funktionen als Rückgabewert verwenden:
function createFunctionThatAddsXtoInput (x) {
function addXtoInput (y) {
return x+y;
}
return addXtoInput;
}
f = createFunctionThatAddsXtoInput(-1)
f(2)
1