Aufwärmen · Aufgabe 1 von 7
Zum Aufwärmen aus Lektion B5.3. Was gibt das aus?
const prices = { tea: 3, cake: 4 };
console.log(Object.entries(prices));// I5.1 · ca. 34 Min. · Aufbau
Nach dieser Lektion legen Sie Daten mit einer Map unter einem Schlüssel ab und schlagen sie nach, entfernen Duplikate mit einem Set und zählen oder gruppieren eine Liste in wenigen Zeilen.
Lektion 1 von 5 in I5 Mit Daten arbeiten
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
const prices = { tea: 3, cake: 4 };
console.log(Object.entries(prices));Vorhersagen · Aufgabe 2 von 7
const seen = {};
seen[1] = "number one";
seen["1"] = "string one";
console.log(Object.keys(seen).length);
const map = new Map();
map.set(1, "number one");
map.set("1", "string one");
console.log(map.size);Üben · Aufgabe 3 von 7
const unique = [...new ____(["de", "en", "de", "fr"])];Üben · Aufgabe 4 von 7
Üben · Aufgabe 5 von 7
const words = ["a", "b", "a", "c", "a"];
const counts = new Map();
for (const word of words) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
console.log([...counts]);Denksport · Aufgabe 6 von 7
const settings = new Map();
settings["theme"] = "dark";
console.log(settings.size, settings.has("theme"));Anwenden · Aufgabe 7 von 7
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
Eine Liste von Website-Besuchen wird zu drei Antworten. Ein Set liefert die Besucher, jeden einmal. Eine Map zählt die Aufrufe pro Seite. Eine zweite Map gruppiert die Besucher nach Seite: pushTo() nutzt ES2026-getOrInsert, wo die Laufzeit es hat, und anderswo das klassische has/set-Muster, gibt also in jeder Laufzeit dasselbe aus. Ein Objekt als Schlüssel zeigt, dass eine Map Schlüssel nach Identität findet, und Object.fromEntries bereitet die Zähler für JSON vor.
main.js
// Visits to a small website: [visitor, page].
const visits = [
["ada", "/home"], ["bo", "/blog"], ["ada", "/blog"],
["cy", "/home"], ["bo", "/blog"], ["ada", "/home"],
];
// 1. A Set keeps each value once, in the order it first came.
const visitors = new Set(visits.map(([visitor]) => visitor));
console.log("visitors:", visitors.size, [...visitors].join(", "));
// 2. Counting: one Map entry per page.
const views = new Map();
for (const [, page] of visits) {
views.set(page, (views.get(page) ?? 0) + 1);
}
for (const [page, count] of views) console.log(page, count);
// 3. Grouping: page -> array of visitors.
function pushTo(map, key, value) {
if (typeof Map.prototype.getOrInsert === "function") {
map.getOrInsert(key, []).push(value); // ES2026 shortcut
} else {
if (!map.has(key)) map.set(key, []); // the classic way
map.get(key).push(value);
}
}
const byPage = new Map();
for (const [visitor, page] of visits) pushTo(byPage, page, visitor);
console.log("/blog:", byPage.get("/blog").join(" "));
// 4. Any value can be a key, even an object.
const ada = { name: "Ada" };
const lastSeen = new Map([[ada, "/home"]]);
console.log(lastSeen.get(ada), lastSeen.get({ name: "Ada" }));
// 5. Back to a plain object, for JSON.
console.log(JSON.stringify(Object.fromEntries(views)));
Ausführen mit
node main.jsAusgabe
visitors: 3 ada, bo, cy
/home 3
/blog 3
/blog: bo ada bo
/home undefined
{"/home":3,"/blog":3}Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Übung 1 von 2
countWords(text) soll eine Map von jedem Wort auf seine Häufigkeit zurückgeben, ohne Beachtung der Groß- und Kleinschreibung: countWords("The cat and the hat").get("the") ist 2. Wörter sind durch einzelne Leerzeichen getrennt. Der Startcode setzt jeden Zähler auf 1. Korrigieren Sie ihn so, dass ein erneut gesehenes Wort seinen Zähler um 1 erhöht.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Führen Sie die Tests aus: the wird einmal gezählt. Was tut der Startcode, wenn er ein Wort zum zweiten Mal sieht?
Lesen Sie zuerst den alten Zähler. counts.get(word) ist für ein neues Wort undefined.
counts.set(word, (counts.get(word) ?? 0) + 1);
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function countWords(text) {
const counts = new Map();
for (const word of text.toLowerCase().split(" ")) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
return counts;
}
Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
export function countWords(text) {
const counts = new Map();
for (const word of text.toLowerCase().split(" ")) {
counts.set(word, 1);
}
return counts;
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {countWords} from './main.js';
test('countWords gibt eine Map zurück', () => {
const counts = countWords('a b');
assert.ok(counts instanceof Map, `countWords gab ${counts} zurück, keine Map`);
});
test('Ein wiederholtes Wort wird jedes Mal gezählt', () => {
const counts = countWords('the cat and the hat');
assert.equal(counts.get('the'), 2, `the wurde ${counts.get('the')}-mal gezählt`);
assert.equal(counts.get('cat'), 1, `cat wurde ${counts.get('cat')}-mal gezählt`);
});
test('Die Schreibweise wird ignoriert, die Reihenfolge ist die des ersten Auftretens', () => {
const counts = countWords('Go go GO stop');
assert.deepEqual([...counts], [['go', 3], ['stop', 1]], `die Einträge sind ${JSON.stringify([...counts])}`);
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenÜbung 2 von 2
groupOrders(orders) bekommt Objekte wie {id: 7, customer: "ada"} und soll eine Map von jedem Kunden auf das Array seiner Bestell-IDs zurückgeben, in Reihenfolge. Der Startcode legt für jede Bestellung ein neues Array an, sodass jeder Kunde nur die letzte ID behält. Legen Sie das Array nur für einen neuen Kunden an und hängen Sie dann an. Nutzen Sie has und set; verlassen Sie sich nicht auf getOrInsert.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Führen Sie die Tests aus: ada hat nur [4]. Wann läuft byCustomer.set(order.customer, [])?
Legen Sie das leere Array nur an, wenn der Kunde noch nicht in der Map ist: byCustomer.has(order.customer).
if (!byCustomer.has(order.customer)) byCustomer.set(order.customer, []);
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function groupOrders(orders) {
const byCustomer = new Map();
for (const order of orders) {
if (!byCustomer.has(order.customer)) byCustomer.set(order.customer, []);
byCustomer.get(order.customer).push(order.id);
}
return byCustomer;
}
Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
export function groupOrders(orders) {
const byCustomer = new Map();
for (const order of orders) {
byCustomer.set(order.customer, []);
byCustomer.get(order.customer).push(order.id);
}
return byCustomer;
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {groupOrders} from './main.js';
const orders = [
{id: 1, customer: 'ada'},
{id: 2, customer: 'bo'},
{id: 3, customer: 'ada'},
{id: 4, customer: 'ada'}
];
test('Jeder Kunde behält alle seine Bestell-IDs', () => {
const groups = groupOrders(orders);
assert.deepEqual(groups.get('ada'), [1, 3, 4], `ada hat ${JSON.stringify(groups.get('ada'))}`);
assert.deepEqual(groups.get('bo'), [2], `bo hat ${JSON.stringify(groups.get('bo'))}`);
});
test('Die Kunden kommen in der Reihenfolge ihrer ersten Bestellung', () => {
const groups = groupOrders(orders);
assert.deepEqual([...groups.keys()], ['ada', 'bo'], `die Schlüssel sind ${JSON.stringify([...groups.keys()])}`);
});
test('Keine Bestellungen ergeben eine leere Map', () => {
const groups = groupOrders([]);
assert.equal(groups.size, 0, `die Map hat ${groups.size} Einträge`);
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenconst prices = new Map();
prices["tea"] = 3;
console.log(prices.get("tea").toFixed(2));
Was Node.js ausgibt
TypeError: Cannot read properties of undefined (reading 'toFixed')Warum, und die Lösung
prices["tea"] = 3 fügt dem Map-Objekt eine gewöhnliche Eigenschaft hinzu. Die Einträge der Map bleiben leer, prices.get("tea") ist also undefined. Schreiben Sie mit prices.set("tea", 3) und lesen Sie mit prices.get("tea"). Dasselbe gilt für has, delete und size: Sie sehen nur Einträge, die mit set angelegt wurden.
const prices = new Map({ tea: 3, cake: 4 });
console.log(prices.size);
Was Node.js ausgibt
TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))Warum, und die Lösung
new Map will eine Liste von [key, value]-Paaren, kein einfaches Objekt. Machen Sie das Objekt zuerst zu Paaren: new Map(Object.entries({ tea: 3, cake: 4 })). Der Weg zurück ist Object.fromEntries(map).
const byPage = new Map();
for (const [visitor, page] of [["ada", "/home"], ["bo", "/blog"]]) {
byPage.get(page).push(visitor);
}
Was Node.js ausgibt
TypeError: Cannot read properties of undefined (reading 'push')Warum, und die Lösung
Beim ersten Auftreten einer Seite hat die Map noch kein Array dafür, get liefert also undefined, und push scheitert. Legen Sie für einen neuen Schlüssel zuerst das Array an: if (!byPage.has(page)) byPage.set(page, []); dann byPage.get(page).push(visitor). Wo ES2026-getOrInsert existiert, erledigt byPage.getOrInsert(page, []).push(visitor) beides.
JavaScript im Browser: die eigene Engine Ihres Browsers in einem abgeschotteten Worker. Syntaxfehler findet acorn 8.18.0, MIT. Lizenz und Quellcode
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.