Kapitel 16, Serverseitiges JavaScript mit Node
Stellt die Hostumgebung von Node vor und behandelt das grundlegende Programmiermodell sowie die für das Verständnis wichtigsten Datenstrukturen und APIs.
Kapitel 17, JavaScript-Werkzeuge und -Erweiterungen
Deckt weitverbreitete Werkzeuge und Spracherweiterungen ab, die man kennen sollte und die Sie zu einem produktiveren Programmierer machen können.
1.4Beispiel: Häufigkeitshistogramme
Dieses Kapitel schließt mit einem kurzen, aber nicht trivialen JavaScript-Programm. Beispiel 1-1 ist ein Node-Programm, das Text von der Standardeingabe liest, aus diesem Text ein Häufigkeitshistogramm der vorkommenden Zeichen berechnet und dieses Histogramm ausgibt. Sie können das Programm wie folgt aufrufen, um die Zeichenhäufigkeit seines eigenen Quelltexts zu analysieren:
$ node charfreq.js < charfreq.js
T: ########### 11.22%
E: ########## 10.15%
R: ####### 6.68%
S: ###### 6.44%
A: ###### 6.16%
N: ###### 5.81%
O: ##### 5.45%
I: ##### 4.54%
H: #### 4.07%
C: ### 3.36%
L: ### 3.20%
U: ### 3.08%
/: ### 2.88%
Dieses Beispiel verwendet eine Reihe fortgeschrittener JavaScript-Funktionen und soll demonstrieren, wie JavaScript-Programme in der realen Welt aussehen können. Falls Sie den Code noch nicht vollständig verstehen, macht das nichts – ich verspreche Ihnen, dass in den folgenden Kapiteln alles erklärt wird.
Beispiel 1-1: Berechnung von Häufigkeitshistogrammen mit JavaScript
/**
* Dieses Node-Programm liest Text aus der Standardeingabe, berechnet für
* jedes Zeichen in diesem Text die Häufigkeit seines Vorkommens und zeigt
* ein Histogramm der am häufigsten verwendeten Zeichen. Zur Ausführung ist
* Node 12 oder höher erforderlich.
*
* In einer Unix-artigen Umgebung können Sie das Programm wie folgt aufrufen:
* node charfreq.js < corpus.txt
*/
// Diese Klasse erweitert Map so, dass die get()-Methode statt null den angegebenen
// Wert zurückgibt, falls der Schlüssel key nicht in der Map vorkommt.
class DefaultMap extends Map {
constructor(defaultValue) {
super(); // Ruft den Konstruktor der Superklasse auf.
this.defaultValue = defaultValue; // Standardwert merken.
}
get(key) {
if (this.has(key)) { // Wenn der Schlüssel bereits in der Map
// vorkommt,
return super.get(key); // wird dessen Wert aus der Superklasse
// zurückgegeben.
}
else {
return this.defaultValue; // Gibt ansonsten den Standardwert zurück.
}
}
}
// Diese Klasse berechnet und zeigt Buchstabenhäufigkeitshistogramme.
class Histogram {
constructor() {
this.letterCounts = new DefaultMap(0); // Zuordnung von Buchstaben
// zu Zählwerten.
this.totalLetters = 0; // Wie viele Buchstaben insgesamt?
}
// Diese Funktion aktualisiert das Histogramm mit den Zeichen des Texts.
add(text) {
// Entfernt Leerzeichen aus dem Text und konvertiert in Großbuchstaben.
text = text.replace(/\s/g, "").toUpperCase();
// Schleife über die Zeichen des Texts.
for(let character of text) {
let count = this.letterCounts.get(character); // Alten Zählwert auslesen.
this.letterCounts.set(character, count+1); // Inkrementieren.
this.totalLetters++;
}
}
// Konvertiert das Histogramm in eine Zeichenfolge, die eine ASCII-Grafik anzeigt.
toString() {
// Konvertiert die Map in ein Array von Schlüssel/Wert-Arrays.
let entries = […this.letterCounts];
// Sortiert das Array zuerst nach Anzahl und dann alphabetisch.
entries.sort((a,b) => { // Eine Funktion zur Festlegung der
// Sortierreihenfolge.
if (a[1] === b[1]) { // Wenn die Zählwerte identisch ist.
return a[0] < b[0] ? -1 : 1; // Alphabetisch sortieren.
} else { // Wenn die Zählwerte abweichen.
return b[1] - a[1]; // Sortierung nach der höchsten Anzahl.
}
});
// Rechnet die Ergebnisse in Prozentzahlen um.
for(let entry of entries) {
entry[1] = entry[1] / this.totalLetters*100;
}
// Alle Einträge unter 1 % fallen lassen.
entries = entries.filter(entry => entry[1] >= 1);
// Konvertiert jeden Eintrag in eine Textzeile.
let lines = entries.map(
([l,n]) => `${l}: ${"#".repeat(Math.round(n))} ${n.toFixed(2)}%`
);
// Und gibt die verketteten Zeilen, getrennt durch Zeilenumbruchzeichen,
// zurück.
return lines.join("\n");
}
}
// Diese asynchrone (ein Promise zurückgebende) Funktion erzeugt ein Histogrammobjekt,
// liest Textblöcke asynchron aus der Standardeingabe und fügt diese Blöcke dem
//