Tutorials › Teil 1: Grundlagen
Kapitel 6 von 16
Funktionen schreiben
Eine Funktion ist ein Stück Code mit einem Namen. Du schreibst es einmal hin und rufst es beliebig oft auf.
function begruessen(name) {
return `Hallo ${name}.`;
}
zeige(begruessen("Mathilda"));
zeige(begruessen("Tobias"));
zeige(begruessen("die Katze"));
Drei Aufrufe, eine Definition. Wenn sich die Begrüßung ändern soll, änderst du eine Zeile statt drei.
Hinein und heraus
Was in den Klammern der Definition steht, sind die Parameter. Was beim Aufruf in den Klammern steht, sind die Argumente. Der Unterschied ist der zwischen Beschriftung und Inhalt.
return beendet die Funktion und gibt einen Wert zurück. Alles nach return wird nicht mehr ausgeführt.
function pruefen(zahl) {
if (zahl < 0) {
return "negativ";
}
return "nicht negativ";
}
zeige(pruefen(-5));
zeige(pruefen(3));
Ohne return liefert eine Funktion undefined. Das ist kein Fehler, viele Funktionen sollen gar nichts zurückgeben, sondern etwas tun.
function meldung(text) {
zeige("[Protokoll]", text);
}
const ergebnis = meldung("gespeichert");
zeige("Rückgabe war:", ergebnis);
Mehrere Parameter, Vorgabewerte
function flaeche(breite, hoehe) {
return breite * hoehe;
}
zeige(flaeche(3, 4));
zeige(flaeche(3));
Der zweite Aufruf liefert NaN, weil hoehe fehlt und 3 * undefined keine Zahl ergibt. Dagegen hilft ein Vorgabewert:
function flaeche(breite, hoehe = breite) {
return breite * hoehe;
}
zeige("Rechteck:", flaeche(3, 4));
zeige("Quadrat: ", flaeche(3));
Der Vorgabewert greift nur bei undefined, nicht bei null und nicht bei 0. Er darf sich auf vorherige Parameter beziehen, wie hier auf breite.
Die Pfeilschreibweise
Es gibt eine zweite Notation, und du wirst sie überall sehen:
const verdoppeln = (x) => x * 2;
const addieren = (a, b) => a + b;
zeige(verdoppeln(21));
zeige(addieren(20, 22));
Bei einem einzelnen Ausdruck darfst du die geschweiften Klammern und das return weglassen. Der Wert des Ausdrucks wird automatisch zurückgegeben.
Wird der Rumpf länger, kommen beide zurück:
const bewerten = (punkte) => {
if (punkte >= 90) return "sehr gut";
if (punkte >= 60) return "bestanden";
return "durchgefallen";
};
zeige(bewerten(95));
zeige(bewerten(40));
Wann nimmt man was? Pfeilfunktionen sind kürzer und eignen sich gut, wenn eine Funktion als Argument an eine andere Funktion geht. Genau das passiert ständig bei Arrays, siehe Kapitel 7.
Für benannte Funktionen auf oberster Ebene bleibt function gut lesbar. Es gibt auch einen inhaltlichen Unterschied beim Schlüsselwort this, aber der interessiert erst bei Objekten und Ereignissen.
Eine Sache noch: function-Deklarationen kannst du aufrufen, bevor sie im Code stehen. Bei const irgendwas = () => {} geht das nicht, die Zeile muss vorher gelaufen sein.
Was drinnen bleibt
Variablen, die innerhalb einer Funktion entstehen, existieren auch nur dort.
function rechnen() {
const zwischenergebnis = 42;
return zwischenergebnis * 2;
}
zeige(rechnen());
zeige("und außerhalb?", typeof zwischenergebnis);
Das ist der Sinn der Sache. Eine Funktion soll eine Kapsel sein. Was sie intern anstellt, geht den Rest des Programms nichts an, und umgekehrt kann der Rest des Programms ihr nicht versehentlich dazwischenfunken.
Umgekehrt sieht eine Funktion alles, was außerhalb von ihr definiert wurde. Das ist bequem und gleichzeitig die häufigste Ursache für unübersichtlichen Code.
Eine Funktion, eine Aufgabe
Hier ist eine Funktion, die zu viel tut:
function verarbeiten(eingabe) {
const zahl = Number(eingabe);
const quadrat = zahl * zahl;
document.getElementById("ausgabe").textContent = quadrat;
console.log("Quadrat berechnet:", quadrat);
localStorage.setItem("letztes", quadrat);
}
Sie rechnet, sie schreibt auf die Seite, sie protokolliert, sie speichert. Willst du nur rechnen, kannst du sie nicht benutzen. Willst du sie testen, brauchst du ein <div> mit der richtigen Kennung, sonst stürzt sie ab.
Zerlegt sieht das so aus:
function quadrieren(zahl) {
return zahl * zahl;
}
function anzeigen(wert) {
zeige("Ergebnis:", wert);
}
const eingabe = "7";
const ergebnis = quadrieren(Number(eingabe));
anzeigen(ergebnis);
quadrieren rechnet und sonst nichts. Man kann sie überall einsetzen, sie hängt von nichts ab, und ob sie stimmt, sieht man in einer Zeile.
Faustregel: Wenn du beim Benennen einer Funktion ein „und" brauchst, sind es zwei Funktionen.
Funktionen als Argument
Funktionen sind in JavaScript ganz normale Werte. Man kann sie in Variablen legen und an andere Funktionen übergeben.
function zweimal(was) {
was();
was();
}
zweimal(() => zeige("Ping"));
zweimal(function () { zeige("Pong"); });
Beachte den Unterschied zwischen was und was(). Ohne Klammern übergibst du die Funktion selbst. Mit Klammern rufst du sie auf und übergibst das Ergebnis. Diese Verwechslung passiert bei Ereignissen dauernd:
element.addEventListener("click", meineFunktion); // richtig
element.addEventListener("click", meineFunktion()); // falsch
Die zweite Zeile ruft die Funktion sofort auf und meldet deren Rückgabewert als Zuhörer an. Der ist meistens undefined, und dann passiert beim Klicken nichts. Mehr dazu in Kapitel 13.
Damit ist der erste Teil durch. Ab hier geht es um die Dinge, mit denen Programme arbeiten, und das beginnt bei Listen.