Studien-Portfolio & Lerntagebuch: Web-Programmierung
Studienbegleitendes Portfolio im Modul „Entwicklung verteilter Systeme“ bei Prof. Dr. Stefan Noll. Diese Webseite dokumentiert alle praktischen Programmierübungen (mit Live-Ausführung und Lernreflexion), das chronologische Lerntagebuch der Vorlesungen sowie das ausgearbeitete Schwerpunktthema.
💻 Säule 1: Programmierübungen
Alle Pflichtübungen (Sternback, *-Dreieck, Bohnen zählen, Währungsrechner, Kontakte-Klasse, Events) live ausführbar inkl. Reflexion.
⭐ Säule 2: Semester-Schwerpunkt
Vertiefungsthema für die Portfolio-Präsentation: Moderne OOP & echte Kapselung in JavaScript (ES6–ES2022 vs. Closures).
📓 Säule 3: Vorlesungs-Lerntagebuch
Strukturierte Aufarbeitung aller Vorlesungen (V1–V5 & HTML 1–5) mit eigenen Erkenntnissen und speicherbaren Notizfeldern.
🎯 Säule 4: Prüfungs- & Kurztest-Trainer
Interaktives Wiederholungs-Quiz zu allen Schlüsselkonzepten für den schriftlichen Kurztest und das Prüfungsgespräch.
Meine Programmierübungen & Pflichtabgaben (Live-Demos & Reflexion)
🫘 Pflichtübung V3: Bohnen zählen ✓ Abgabe erledigt
Aufgabe (V3, Folie 35): Implementierung von countBs(string) und
countChar(string, zeichen) mithilfe von ES6-Pfeilfunktionen
(=>).
countChar(string, zeichen) konnte ich
Code-Duplizierung vermeiden (DRY-Prinzip). countBs wurde als einzeilige
Arrow-Funktion mit implizitem Return umgesetzt:
const countBs = (string) => countChar(string, "B");.
// Funktion countChar mit Pfeilfunktion
const countChar = (string, zeichen) => {
let anzahl = 0;
for (let i = 0; i < string.length; i++) {
if (string[i] === zeichen) {
anzahl++;
}
}
return anzahl;
};
// Funktion countBs mit Pfeilfunktion (nutzt countChar)
const countBs = (string) => countChar(string, "B");
💶 Pflichtübung V4: Währungsumrechner ✓ Abgabe erledigt
Aufgabe (V4, Folie 53): Formularbasierter Umrechner zwischen 2 Währungen
($ und €) mit Radio-Buttons und Komma-Notation
(replace).
parseFloat() in JavaScript einen Dezimalpunkt erwartet, wandle ich die
deutsche Komma-Eingabe zuerst per eingabeText.replace(",", ".") um, prüfe mit
isNaN() auf Fehleingaben und formatiere das Ergebnis mit
toFixed(2).replace(".", ",") zurück.
function umrechnen() {
let eingabeText = document.getElementById("eingabe").value.trim();
let eingabeMitPunkt = eingabeText.replace(",", ".");
let betrag = parseFloat(eingabeMitPunkt);
if (isNaN(betrag)) { alert("Bitte gültigen Betrag eingeben."); return; }
const KURS_DOLLAR = 1.12;
let richtung = document.querySelector('input[name="richtung"]:checked').value;
let ergebnis = (richtung === "dollarZuEuro") ? (betrag / KURS_DOLLAR) : (betrag * KURS_DOLLAR);
document.getElementById("ausgabe").value = ergebnis.toFixed(2).replace(".", ",");
}
📐 Pflichtübung V2: *-Dreieck ✓ Abgabe erledigt
Aufgabe (V2, Folie 59): Ausgabe eines *-Dreiecks in HTML und
auf der Konsole mithilfe geschachtelter Schleifen nach Benutzereingabe der Zeilenanzahl.
prompt() immer einen String zurückliefert, wende ich
parseInt(..., 10) an. Die äußere Schleife (i = 1..zeilen) steuert
die Zeilen, während die innere Schleife (j = 1..i) pro Zeile genau
i Sterne verkettet.
let zeilen = parseInt(prompt("Bitte geben Sie die Anzahl der Zeilen ein:"), 10);
for (let i = 1; i <= zeilen; i++) {
let sternZeile = "";
for (let j = 1; j <= i; j++) {
sternZeile += "*";
}
console.log(sternZeile);
document.write(sternZeile + "<br>");
}
📇 Pflichtübung V5: Klasse Kontakte ✓ Abgabe
erledigt
Aufgabe (V5, Folie 65): ES2022-Klasse mit privaten Eigenschaften
(#), static gesamtZahl, get/set-Methoden
und checkUser().
#-Syntax sind Felder wie #vorname und
#laufendeNummer echt gekapselt: Ein Direktzugriff von außen führt zu einem
SyntaxError. Die statische Variable Kontakte.gesamtZahl wird im
Konstruktor bei jeder Instanziierung hochgezählt.
class Kontakte {
static gesamtZahl = 0;
#laufendeNummer; #vorname; #nachname; #telMobil; #email; #wohnort;
constructor(vorname, nachname, telMobil, email, wohnort) {
Kontakte.gesamtZahl++;
this.#laufendeNummer = Kontakte.gesamtZahl;
this.#vorname = vorname;
this.#nachname = nachname;
this.#telMobil = telMobil;
this.#email = email;
this.#wohnort = wohnort;
}
// get + set für ALLE privaten Instanzvariablen
get laufendeNummer() { return this.#laufendeNummer; }
set laufendeNummer(nr) { this.#laufendeNummer = Number(nr); }
get vorname() { return this.#vorname; }
set vorname(v) { this.#vorname = v; }
get nachname() { return this.#nachname; }
set nachname(n) { this.#nachname = n; }
get telMobil() { return this.#telMobil; }
set telMobil(t) { this.#telMobil = t; }
get email() { return this.#email; }
set email(e) { this.#email = e; }
get wohnort() { return this.#wohnort; }
set wohnort(w) { this.#wohnort = w; }
checkUser(v, n) { return this.#vorname === v && this.#nachname === n; }
getKontaktDaten() { return `#${this.#laufendeNummer}: ${this.#vorname} ${this.#nachname} (${this.#telMobil}, ${this.#email}, ${this.#wohnort})`; }
}
☕ HTML-Übung 1: Sternback-Kaffee ✓ Erledigt
Aufgabe (HTML Teil 1): Umsetzung der Sternback-Getränkekarte mit semantischen Überschriften, Absätzen und individuellem CSS-Design.
<h1>, <h2>,
<p>) habe ich das Layout in sternback.html mit einem
modernen Farbverlauf (linear-gradient), abgerundeten Ecken
(border-radius), box-shadow und hervorgehobenen Preisen
(<strong>) erweitert.
Getränke bei Sternback-Kaffee
Hausmischung, € 1.49
Eine feine, milde Mischung verschiedener Kaffeesorten aus Mexiko, Bolivien und Guatemala.
Mokka Café Latte, € 2.35
Espresso, heiße Milch und Schokosirup.
Cappuccino, € 1.89
Eine Mischung aus Espresso, heißer Milch und Milchschaum.
Chai-Tee, € 1.85
Eine würzige Mélange aus schwarzem Tee, Gewürzen, Milch und Honig.
<h1>Getränke bei <br>Sternback-Kaffee</h1>
<h2>Hausmischung, <strong style="color: black;">€ 1.49</strong></h2>
<p>Eine feine, milde Mischung verschiedener Kaffeesorten aus Mexiko, Bolivien und Guatemala.</p>
🖱️ Übungen V1 & V2: Events, Dialoge & Zahlenraten ✓ Erledigt
Aufgaben: Event-Handling mit onclick (test1.html),
Benutzereingabe via prompt() (event.html) und das
Zahlenraten-Spiel (V2).
onclick="alert('Hello')" müssen
innen einfache Anführungszeichen stehen. Beim Zahlenraten-Spiel nutzt JS automatische
Typkonvertierung (Type Coercion) beim Vergleich des prompt()-Strings mit der
Zufallszahl.
<!-- test1.html -->
<input type="button" value="Drücke mich" onclick="alert('Hello')">
<!-- event.html -->
<script>alert("Sie sind " + prompt("Wie alt sind Sie? ") + " Jahre alt");</script>
Vertiefungsthema: Objektorientierung, Kapselung & this-Kontext in modernem
JavaScript
⭐ Ausarbeitung für die Portfolio-Präsentation (5–10 Minuten)
Gemäß den Vorgaben zur Portfolioprüfung (Vorlesung 1, Folie 14) vertieft dieser Schwerpunkt die
Entwicklung der Objektorientierung in JavaScript – von klassischen Konstruktorfunktionen und
Closure-Kapselung bis hin zu modernen ES6-Klassen, ES2022 Private
Fields (#) und der Lösung des
this-Kontextverlusts bei Callbacks/Events.
1. Vergleich: Kapselung über Closures vs. ES2022 #-Felder
| Kriterium | Closure im Konstruktor (Vor ES2022) | ES2022 Private Fields (#prop) |
|---|---|---|
| Syntax | Lokale Variable let _name = name; im Konstruktor |
Deklaration #name; direkt im class-Körper |
| Zugriff von außen | obj._name liefert undefined (legt bei
Zuweisung versehentlich neue Public-Property an!) |
Wird bereits vom JS-Parser blockiert: wirft sofort
SyntaxError! |
| Speicherverbrauch | Jede privilegierte Methode muss pro Instanz neu im Konstruktor erzeugt werden. | Methoden liegen effizient auf dem Prototyp und können trotzdem auf
this.#name zugreifen! |
2. Warum geht this in Event-Handlern & Callbacks verloren?
In Java ist this fest an die Instanz gebunden. In JavaScript hängt
this allein vom Aufrufkontext zur Laufzeit ab:
class Zaehler {
#wert = 0;
// Problem: Klassische Methode verliert 'this', wenn sie als Callback übergeben wird!
erhoehenKlassisch() { this.#wert++; }
// Lösung A: Arrow-Property (bindet 'this' lexikalisch an die Instanz)
erhoehenSicher = () => { this.#wert++; return this.#wert; };
}
Vorlesung 1: Web-Anwendungen, Architekturen & Skriptsprachen
🌐 Client-Server & 3 Software-Architekturen
- Rein client-seitig (Rich Client): Server liefert HTML + Programm (z.B.
neueAnw.jarvia Java Web Start). - Rein server-seitig: Server führt Skripte/Programme aus (PHP, Java Servlets, JSP, CGI), fragt Datenbank ab und schickt fertiges HTML an den Browser.
- Moderne Hybrid-Architektur (Client + Server):
- Client-seitig (JS + DOM): Dokumentänderung direkt im Browser (Plausibilitäts-Checks, Formularanpassung, lokale Dialoge, Animationen, asynchrone Interaktivität wie Autocomplete).
- Server-seitig: Datenbankanbindung & Geschäftslogik. (Wichtig: Java ≠ JavaScript!).
⚙️ Compiler vs. Interpreter & Erste JS-Regeln
- Compiler (z.B. Java, C++): Übersetzt komplett vorab; statische Semantik prüft Typ- und Bindungsregeln vor der Ausführung.
- Interpreter (z.B. JavaScript, PHP): Führt Code direkt aus; Bindungs- und Typregeln werden erst zur Laufzeit geprüft (nicht ausgeführte Zweige bleiben ungeprüft!).
- Erste JS-Grundregeln:
alert(17 + 5 * 3)berechnet32; in Anführungszeichenalert("17 + 5 * 3")wird es als Text ausgegeben.- In HTML-Attributen wie
onclick="alert('Hallo!')"müssen einfache und doppelte Anführungszeichen abgewechselt werden. <noscript>wird nur angezeigt, wenn JavaScript im Browser deaktiviert ist.
📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 1 (wird lokal gespeichert):
Vorlesung 2: Konsole, Dynamische Typisierung, Scope, Arrays & Operatoren
📦 Dynamische Typisierung, let / const / var &
Scope
- Dynamische Typisierung: Variablen haben keinen festen Typ bei der
Deklaration; JS kennt nur
numberfür Ganz- und Fließkommazahlen. let&const(ab ES6): Haben Block-Scope ({ ... }).varhat nur Funktions-Scope.- Kritische Fehlerquelle: Lässt man
let/const/varbei einer Zuweisung in einer Funktion weg (z.B.y = 17;), wirdyautomatisch als globale Variable angelegt!"use strict";am Skriptanfang verhindert dies. undefinedvs.null: Nicht initialisierte Variablen/fehlende Parameter sind automatischundefined;nullweist man explizit als „leeren Wert“ zu.
Ursprünglicher Text
📚 Array-Methoden, Template-Literale & Operatoren
- Template-Literale (Backticks):
`Die Hälfte von 100 ist ${100 / 2}`(erlaubt Zeilenumbrüche und Berechnungen). - Strikte Gleichheit:
===und!==prüfen Wert und Datentyp (keine implizite Typumwandlung wie bei==). - Die 14 Array-Methoden (Folie 41):
- Ende:
push()(anfügen),pop()(entfernen) - Anfang:
unshift()(einfügen),shift()(entfernen) - Teile & Umbau:
slice(),splice(),concat(),join(),reverse(),sort() - Funktional:
forEach(),map(),filter(),reduce()
- Ende:
📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 2:
Vorlesung 3: First-Class Functions, Arrow-Syntax, Rest/Spread & Pure Functions
🥇 4 Arten der Funktionserzeugung & Arrow-Kurzformen
- Funktionsanweisung:
function add(a, b) { return a + b; } - Funktionsausdruck:
const add = function(a, b) { return a + b; }; Function-Konstruktor- Pfeilfunktion (Arrow Function
=>):- Einzelner Return-Ausdruck ➔
{ }undreturnweglassen:(a, b) => a + b - Genau 1 Parameter ➔
( )weglassen:x => x * x - 0 Parameter ➔ leere Klammern
()sind Pflicht:() => "Hallo"
- Einzelner Return-Ausdruck ➔
🔄 Rest-Parameter, Spread-Operator & Pure Functions
- Rest-Parameter (
...numbers): Sammelt beliebig viele übergebene Argumente in einem echten Array (im Gegensatz zum alten, nur array-ähnlichenarguments-Objekt). - Spread-Operator (
...): Entpackt Elemente eines Arrays/Objekts. Wichtigste Anwendung: Flache Kopie erzeugen (let copy = { ...orig };), um das Copy-by-Reference-Problem zu lösen! - Pure Function (Reine Funktion): Hängt nur von ihren Parametern ab,
verändert keine externen Variablen oder übergebenen Objekte (Immutability per Spread:
const buyCar = p => ({ ...p, hasCar: true });). - Higher-Order Functions & Closures: Funktionen, die Funktionen als
Parameter erhalten oder als Ergebnis zurückgeben (z.B.
multiplier(factor)).
📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 3:
Vorlesung 4: Das String-Objekt & Formulare im DOM
🧵 String-Methoden & Live-Tester (0-basiert)
.length: Eigenschaft (keine Klammern()!), schreibgeschützt..charAt(index): Zeichen an Positionindex(0-basiert)..indexOf(such [, start])/.lastIndexOf(such [, start]): Sucht vorwärts bzw. rückwärts; gibt-1zurück, wenn nicht gefunden..substring(anfang, ende): Kopiert vonanfang(inklusive) bisende(exklusive!)..split(trennzeichen): Zerlegt String in ein Array von Teilstrings.
📋 Formular-Adressierung & die 10 Formular-Objekte
- 3 Zugriffswege im DOM:
- Über Arrays:
document.forms[0].elements[0] - Über Namen:
document.meinFormular.eingabe1 - Über W3C-DOM:
document.getElementById("eingabe1")(oder relativ im Event überthis.form.eingabe1)
- Über Arrays:
- Besonderheiten der Formular-Elemente:
textarea: Attributwrap="off | virtual | physical".password: Nur optisch maskiert – in JS.valueund beim unverschlüsselten Versand im Klartext!checkbox&radio: Status über.checked. Bei Radiogruppen per Schleife über das Array iterieren!select: Einfachauswahl überselectedIndex; Mehrfachauswahl (multiple) per Schleife überliste[i].selected. Neue Option:liste[liste.length] = new Option("Neu");, Löschen:liste[2] = null;.
📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 4:
Vorlesung 5: Objekte, JSON, ES6-Klassen, Kapselung & Destructuring
🧱 4 Wege der Objekterzeugung & JSON-Regeln
new Object()(allgemeiner Konstruktor)- Objekt-Literal
{ name: "Fred", ... }(Einzelinstanz) - Konstruktorfunktion
function Person(name) { this.name = name; }mitnew - ES6-Klassen
class Person { constructor(name) { ... } }(beiextendsmuss im Subklassen-Konstruktor zuerstsuper()gerufen werden!)
Strenge Regeln für JSON (JavaScript Object Notation):
- Alle Eigenschaftsnamen müssen in doppelten Anführungszeichen
"..."stehen! - Keine Methoden/Funktionen, keine Berechnungen, keine Kommentare!
- Methoden:
JSON.stringify(obj)(Objekt ➔ Text) undJSON.parse(text)(Text ➔ Objekt).
🧩 Destructuring & Object Literal Enhancement
// Array- & Objekt-Destructuring
let [a, b, ...rest] = [44, 67, 90, 56];
const hero = { name: 'Batman', realName: 'Bruce Wayne' };
const { name, realName } = hero;
// Wichtig: Bei bereits deklarierter Variable runde Klammern um die Zuweisung!
let n;
({ name: n } = hero);
// Gegenstück: Object Literal Enhancement
let gipfel = "Zugspitze", hoehe = 2962;
let berg = { gipfel, hoehe };
📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 5:
HTML & CSS Teil 1 bis 5 („Von Kopf bis Fuß“)
📙 HTML 1 & 2: Grundstruktur, Attribute & Relative Pfade
- Anatomie:
Element = Start-Tag + Inhalt + End-Tag. Mehrfache Leerzeichen/Umbrüche (Whitespace) im Quellcode werden vom Browser ignoriert. - Attribute: Immer
name="wert"in doppelten Anführungszeichen (z.B.<a href="ziel.html">). - Relative Pfade:
- Unterordner:
href="getraenke/elixir.html" - Elternordner (eine Ebene höher):
href="../bar.html"(zwei Ebenen:../../) - Pfadtrenner im Web ist immer
/(Forward-Slash)!
- Unterordner:
📙 HTML 3: Block vs. Inline, Zitate, Listen & Entities
- Block-Elemente (eigener Umbruch):
<h1>–<h6>,<p>,<blockquote>,<ol>,<ul>,<li>. - Inline-Elemente (im Textfluss):
<q>,<a>,<em>,<strong>,<img>,<code>. - Inhaltsleere Elemente (Void):
<br>,<img>,<link>,<meta>. - Listen:
<ol>(nummeriert) und<ul>(Punkte) dürfen direkt nur<li>enthalten! Definitionsliste:<dl>mit<dt>und<dd>. - Entities:
>(>),<(<),&(&),ä,ö,ü,ß.
📙 HTML 4 & 5: CSS-Regeln, Externe Stylesheets, Vererbung & Spezifität
- CSS-Regel:
Selektor { eigenschaft: wert; }(Gruppierung mit Komma:h1, h2 { ... }). - Externes Stylesheet:
<link type="text/css" rel="stylesheet" href="bar.css">im<head>. In der.css-Datei dürfen keine<style>-Tags stehen! - Vererbung: Text-Eigenschaften (
color,font-family) werden im DOM-Baum vererbt; Rahmen/Box-Eigenschaften (border) nicht.
- Klassen & Konfliktlösung (Kaskade):
- Spezifität gewinnt:
p.gruenerteeschlägt.gruenertee, und.gruenerteeschlägtp. - Bei gleicher Spezifität: Es gewinnt die Regel, die
in der CSS-Datei am weitesten unten (zuletzt) steht! Die
Reihenfolge in
class="a b c"im HTML ist egal.
- Spezifität gewinnt:
Interaktiver Kurztest- & Prüfungstrainer (Vorlesung 1 bis 5 & HTML/CSS)
🎯 Wissens-Check für den 20-Punkte-Kurztest & die mündliche Portfolioprüfung
Beantworte die folgenden typischen Prüfungsfragen aus den Vorlesungsskripten von Prof. Dr. Noll: