17.10.2020

Funktionen, Parameter und Rückga­bewerte

Grundwissen Programmieren Teil 2

Funktionen, Parameter und Rückga­bewerte

Dies ist Teil 2 unserer Blogpost-Serie “Grundwissen Programmieren”.

In meinem letzten Blog-Post habe ich euch gezeigt, wie man Variablen in JavaScript benutzt, was Datentypen sind, und wie die verschiedenen Operatoren funktionieren.

In diesem Blog-Post schauen wir uns Funktionen an. Du siehst, wie man Funktionen in JavaScript erstellt und benutzt, wie du Daten an eine Funktion übergibst und wie du einen Rückgabewert von ihr bekommst.

Lass uns direkt eintauchen. 🏊‍♀️

Schau dir den folgenden JavaScript-Code an:

var age = 19;
 
// Can we have a soda?
if (age > 1) {
  console.log("Here you go!")
} else {
  console.log("Not old enough, sorry.")
}
 
// Can we have a beer?
if (age >= 18) {
  console.log("Here you go!")
} else {
  console.log("Not old enough, sorry.")
}
 
// Can we have wine?
if (age >= 18) {
  console.log("Here you go!")
} else {
  console.log("Not old enough, sorry.")
}
 
// Can we have wodka?
if (age >= 21) {
  console.log("Here you go!")
} else {
  console.log("Not old enough, sorry.")
}

Du kannst dir immer alle Code-Beispiele dieses Blog-Posts hier anschauen und ausprobieren. Ich empfehle dir, dir ein eigenes Repl auf replit.com anzulegen und dort die Beispiele selbst auszuprobieren. Learning by Doing ist die beste Methode um Programmieren zu lernen.

In dem Beispiel oben wird ein Code-Schnipsel mehrmals verwendet. Diese Zeilen gibt es doppelt:

if (age >= 18) {
  console.log("Here you go!")
} else {
  console.log("Not old enough, sorry.")
}

und auch zwei andere Code-Blöcke sind dem sehr ähnlich.

Diese Wiederholung macht den Code sehr lang. Das können wir verhindern. Wir können die Code-Schnipsel, die sich wiederholen, in einen Block auslagern. Dieser Code-Block bekommt dann einen Namen, womit wir ihn überall, wo wir ihn brauchen, benutzen können.

Das nennt man eine Funktion (engl.: function).

Funktionen

Wenn wir das Beispiel von oben nehmen und den doppelt vorkommenden Code-Block in eine Funktion auslagern, würde das so aussehen:

function canWeDrinkThis() {
  if (age >= 18) {
    console.log("Here you go!")
  } else {
    console.log("Not old enough, sorry.")
  }
}

Das function-Keyword sagt uns: hier wird eine Funktion festgelegt!
Darauf folgt der Name der Funktion (canWeDrinkThis). Du kannst eine Funktion nennen, wie du möchtest.
Auf den Namen der Funktion folgen die beiden Klammern: ().
Direkt danach kündigt eine öffnende geschweifte Klammer { an: hier fängt der Code-Block der Funktion an! Dieser endet mit der schließenden geschweiften Klammer }, die anzeigt, dass hier die Funktion zuende ist.
Innerhalb der geschweiften Klammern kommt dann der Code-Block, den die Funktion ausführen soll.

Dies ist bisher aber nur die “Definition” der Funktion. Wir nennen das in der Softwareentwicklung die Funktions-Deklaration (engl.: function declaration).
Was bedeutet das genau? Es bedeutet, dass wir gerade definiert haben, was die Funktion tun wird.
Um die Funktion tatsächlich auszuführen, damit das, was im Block der Funktion steht, auch gemacht wird, müssen wir die Funktion aufrufen:

canWeDrinkThis()

Man ruft eine Funktion auf indem man den Namen der Funktion, gefolgt von den runden Klammern (), anführt. Das ist dann der Funktionsaufruf (engl.: function call).

Wichtig: Man deklariert zuerst die Funktion, dann ruft man sie auf. Es ist wichtig, dass du dir den Unterschied zwischen Funktionsdeklaration und Funktionsaufruf gut einprägst. Wenn das gerade alles noch etwas verwirrend ist - keine Angst. Mit der entsprechenden Übung wird das alles noch viel klarer.

Die Funktion wird erst ausgeführt, wenn sie aufgerufen wird. Man kann eine Funktion so oft wie man möchte und an den verschiedenen Stellen im Code aufrufen, wo man sie braucht.

Du kannst das einmal ausprobieren, indem du die Funktion mehrmals hintereinander aufrufst:

canWeDrinkThis()
canWeDrinkThis()
canWeDrinkThis()

Was passiert, wenn du diesen Code ausführst? Die Funktion wird drei mal hintereinander ausgeführt, und du bekommst drei mal den gleichen Output auf der Konsole.

Mit Funktionen ist es ein bisschen wie mit einem Rezept: Die Funktions-Deklaration ist wie wenn man das Rezept auf ein Blatt Papier schreibt. Der Funktions-Aufruf ist dann als würde man das Gericht tatsächlich zubereiten.

Bei Rezepten hat man ja meistens am Beginn eine Liste an Zutaten, die man für das Gericht braucht. Funktionen haben ein ähnliches Konzept: Parameter.

Parameter

Parameter sind Daten, die in eine Funktion gegeben werden: der Input einer Funktion.

Man nennt Parameter auch oft kurz: Params.

Wenn man sich das erste Beispiel von oben anschaut, sieht man: es gibt vier Blöcke, die sich sehr ähneln. Das Einzige, was sich ändert, ist das Mindestalter für jedes Getränk. Wir könnten nun unsere Funktion so anpassen, dass sie das berücksichtigt, indem wir Parameter benutzen. Wir können das Mindestalter als Parameter an die Funktion übergeben.

Das würde so aussehen:

function canWeDrinkThis(minAge) {
  if (age >= minAge) {
    console.log("Here you go!")
  } else {
    console.log("Not old enough, sorry.")
  }
}

Das minAge ist das erlaubte Mindestalter für das Getränk. Das wird hier als Parameter übergeben.

Für Bier, beispielsweise, ist das Mindestalter 18. Wir können das dann entsprechend beim Funktionsaufruf in die runden Klammern () schreiben:

canWeDrinkThis(18)

So können wir jedes Getränk mit seinem Mindestalter abfragen:

canWeDrinkThis(1)   // Soda
canWeDrinkThis(18)  // Beer
canWeDrinkThis(18)  // Wine
canWeDrinkThis(21)  // Wodka

Alles, was mit zwei Schrägstrichen // anfängt, ist ein Kommentar. Kommentare werden ignoriert und nicht mit ausgeführt.

Was passiert hier nun also? Die Funktion wird vier mal hintereinander ausgeführt, einmal pro Getränk. Das erlaubte Mindestalter wird als Parameter übergeben: 1 für Soda, 18 für Bier, nochmal 18 für Wein und 21 für Wodka. So werden vier Zeilen auf der Konsole ausgegeben, die etwa so aussehen sollten:

Here you go!
Here you go!
Here you go!
Not old enough, sorry.

Nun wäre es ja auch ganz schön zu sehen, welche Zeile zu welchem Getränk gehört. Das können wir erreichen, indem wir den Namen des Getränks als zweiten Parameter übergeben. Den können wir dann in der Funktion dafür benutzen, dass er mit dem console.log("...") mit ausgegeben wird:

function canWeDrinkThis(beverage, minAge) {
  if (age >= minAge) {
    console.log("Here you go! Have a " + beverage)
  } else {
    console.log("Not old enough for " + beverage + ", sorry.")
  }
}

Hier definieren wir einen zusätzlichen Parameter namens beverage.
Dieser Parameter wird dann in dem Block der Funktion wie eine Variable benutzt.

Wenn du noch nicht mit Variablen vertraut bist, schau dir diesen Blog-Post an, wo wir Variablen erklären.

In den console.log-Ausgaben benutzen wir dann den Parameter beverage und geben ihn als Teil des Ausgabetextes aus.

Wie wir oben gelernt haben, ist dies aber nur die Funktionsdeklaration. Wir müssen sie auch noch aufrufen, damit sie ausgeführt wird. Am besten rufen wir sie einmal pro Getränk auf:

canWeDrinkThis("Soda", 1)
canWeDrinkThis("Beer", 18)
canWeDrinkThis("Wine", 18)
canWeDrinkThis("Wodka", 21)

Das sollte eine Ausgabe ergeben, die so aussieht:

Here you go! Have a Soda
Here you go! Have a Beer
Here you go! Have a Wine
Not old enough for Wodka, sorry.

Pro Getränk haben wir nun eine Zeile Konsolen-Output.

Datentypen von Parametern

Wie du dich sicher von unserem vorherigen Blog Post erinnerst, haben Variablen immer einen Datentyp, z.B. Integer (eine ganze Zahl) oder String (Text). Das Gleiche gilt auch für Parameter. Parameter sind quasi eine spezielle Art von Variablen, nämlich Variablen, die an Funktionen übergeben werden.

Im Funktionsaufruf

canWeDrinkThis("Beer", 18)

sieht man ganz schön, dass hier zwei Parameter von unterschiedlichem Datentyp übergeben werden: der erste, der Name des Getränks, ist ein String, der zweite, das Mindestalter für das Getränk, ist ein Integer.

In der Funktionsdeklaration müssen wir da achtsam sein, weil man hier die Datentypen quasi nicht sieht. Man sieht nur die Namen der Parameter:

function canWeDrinkThis(beverage, minAge) { ...

Wir müssen deswegen mitdenken, und uns bewusst machen, wie der Parameter im Block der Funktion benutzt wird.

In unserem Fall wird beverage später im Code als ein String benutzt:

  console.log("Here you go! Have a " + beverage)

Und minAge wird als Integer benutzt:

  if (age >= minAge) { ...

Deswegen müssen wir dann, wenn wir die Funktion aufrufen, darauf achten, dass wir den richtigen Datentypen an der richtigen Stelle benutzen. In diesem Fall: an erster Stelle ein String (Strings werden immer in Anführungszeichen geschrieben) und an zweiter Stelle als Integer (nur die Zahl).

canWeDrinkThis("Beer", 18)

Das ist nichts, worum du dir Sorgen machen solltest, aber du solltest zumindest aufmerksam damit sein, wenn du die Funktion deklarierst und dann ausführst.

Rückgabewerte

Funktionen können einen Rückgabewert haben. Was bedeutet das?
Es bedeutet, dass wir Funktionen so schreiben können, dass sie etwas zurück geben. In anderen Worten: wir können einen Output von der Funktion bekommen.

Schauen wir uns diese Funktion einmal an:

function isOldEnough(age, minAge) {
  var oldEnough = age >= minAge;
  return oldEnough;
}

Diese Funktion gibt true oder false zurück, weil sie einen Rückgabewert hat:

return oldEnough;

Hierbei ist oldEnough die Variable, die in der Zeile oben drüber erstellt worden ist.
Mit return geben wir sie zurück: wir legen fest, dass die Funktion das zurück geben soll, was auch immer gerade der Wert von oldEnough ist (true oder false).

Wenn wir die Funktion dann aufrufen, bekommen wir einen Wert zurück. Den können wir zum Beispiel in einer Variable speichern:

var canDrink = isOldEnough(19, 18);

isOldEnough(19, 18) ist der Funktionsaufruf - wir rufen hier unsere neue Funktion mit den Parametern age (19) und minAge (18) auf.

Dann speichern wir sie in einer Variable: var canDrink.

Du kannst die Variable auf der Konsole ausgeben um zu sehen, welchen Wert sie hat:

console.log(canDrink)

Wenn du die Funktion oben mit 19 und 18 aufgerufen hast, sollte der Output auf der Konsole hier true sein.

Spiel ruhig ein wenig damit herum, ändere die Zahlen, die du an die Funktion übergibst, und beobachte, wie sich das Ergebnis verändert.

Das Endergebnis

Bringen wir einmal alles, was wir bisher ausprobiert haben zusammen. Wie würde denn unser Beispiel von ganz oben aussehen, wenn wir Funktionen einsetzen würden?

Zuerst müssen wir dafür unsere Funktionsdeklarationen auflisten. Wir brauchen diese 2 Funktionen:

  • isOldEnough(age, minAge), die true oder false zurück gibt
  • canWeDrinkThis(beverage, minAge), die die Ausgabe auf der Konsole macht

Wenn wir das von unseren Beispielen oben alles übernehmen, sollte das so aussehen:

// Function declarations

function isOldEnough(age, minAge) {
  var oldEnough = age >= minAge
  return oldEnough
}

function canWeDrinkThis(beverage, minAge) {
  var oldEnough = isOldEnough(age, minAge)
  if (oldEnough) {
    console.log("Here you go! Have a " + beverage)
  } else {
    console.log("Not old enough for " + beverage + ", sorry.")
  }
}

Hier rufe ich die Funktion isOldEnough() bereits in der Funktion canWeDrinkThis() auf. Und ja, natürlich kann man Funktionsaufrufe in Funktionsdeklarationen machen. Das ist Gang und Gäbe und die Art, wie Funktionen meistens verwendet werden.

Jetzt gibt es in der Funktion canWeDrinkThis() zwei Zeilen, die man noch kürzer schreiben könnte:

// ...
  var oldEnough = isOldEnough(age, minAge)
  if (oldEnough) {
// ...

Das ist im Prinzip das Gleiche wie wenn man schreibt:

// ...
  if (isOldEnough(age, minAge)) {
// ...

Erkennst du, was ich hier mache? Ich habe auf die neue Variable oldEnough verzichtet und benutzte stattdessen den Funktionsaufruf direkt an der Stelle in der if (...)-Anweisung. Wir haben die Variable durch einen Funktionsaufruf ersetzt.

Das geht deswegen, weil die Funktion einen Rückgabewert hat. Wir wissen, dass der Typ des Rückgabewertes ein Boolean ist, also true oder false. Deswegen können wir die Funktion direkt in die if (...)-Anweisung schreiben.

Beachte: Wenn die Funktion etwas anderes als ein Boolean zurück geben würde, z.B. einen String oder ein Integer, könnten wir sie so nicht in der if (...)-Anweisung benutzen.

Das bedeutet: Wenn die Funktion einen Rückgabewert hat, kann ich den Funktionsaufruf genau wie eine Variable benutzen. Das ist sinnvoll, wenn ich den Funktionsaufruf nur einmal benutze und den zurückgegeben Wert sonst nicht weiter benutzen möchte. In unserem Fall macht es die Funktion eine Zeile kürzer, was immer gut ist. 😊

Wir rufen unsere Funktion isOldEnough() also schon in unserer Funktion canWeDrinkThis() auf. Aber das Wichtigste fehlt noch: wir müssen auch noch die Funktion canWeDrinkThis() aufrufen.
Das machen wir einmal pro Getränk:

// Function calls

var age = 19;

// Can we have a soda?
canWeDrinkThis("Soda", 1)
// Can we have a beer?
canWeDrinkThis("Beer", 18)
// Can we have wine?
canWeDrinkThis("Wine", 18)
// Can we have wodka?
canWeDrinkThis("Wodka", 21)

Das gibt uns den Konsolen-Output, den wir erwarten:

Here you go! Have a Soda
Here you go! Have a Beer
Here you go! Have a Wine
Not old enough for Wodka, sorry.

Und hier ist einmal für deine Übersicht als Zusammenfassung das ganze Programm:

// Function declarations

function isOldEnough(age, minAge) {
  var oldEnough = age >= minAge
  return oldEnough
}

function canWeDrinkThis(beverage, minAge) {
  if (isOldEnough(age, minAge)) {
    console.log("Here you go! Have a " + beverage)
  } else {
    console.log("Not old enough for " + beverage + ", sorry.")
  }
}

// Function calls

var age = 19;

// Can we have a soda?
canWeDrinkThis("Soda", 1)
// Can we have a beer?
canWeDrinkThis("Beer", 18)
// Can we have wine?
canWeDrinkThis("Wine", 18)
// Can we have wodka?
canWeDrinkThis("Wodka", 21)

Wunderschön, oder? 😊 Das ist doch viel kürzer und mit weniger dupliziertem Code als unser Ausgangsbeispiel. Cool! ✨

Du kannst dir das Endergebnis hier anschauen. Du kannst es dort ausführen und ein bisschen damit herumspielen, wenn du magst.

 


 

Gut gemacht! Wenn du diesem Tutorial gefolgt bist, hast du deine ersten Funktionen geschrieben, den Unterschied zwischen Funktionsdeklaration und Funktionsaufruf gelernt, Parameter an Funktionen übergeben und die Funktion einen Rückgabewert zurück geben lassen.

Das ist vor allem am Anfang nicht so einfach. Wenn du das Gefühl hast, dass du nicht alles zu 100% verstanden hast: bleib dran! Spiel ein wenig mit dem Code und schreibe weitere Funktionen. Übung macht den Meister, und mit der Übung kommt auch ein klareres Verständnis zu Funktionen.

Als Übung kannst du die Funktion canWeDrinkThis(...) so anpassen, dass sie einen Rückgabewert von true oder false hat, und den danach auf der Konsole ausgeben. Du kannst dir die Lösung zu dieser Übung hier anschauen.

Wir hoffen, dass dir dieses Tutorial geholfen hat, Funktionen zu verstehen. Bist du gut mitgekommen? Wenn ja, teile den Artikel mit jemandem, der auch Programmieren lernen möchte. Und wenn nicht, schreibe mir und stelle mir gern deine Fragen. Danke für’s Lesen, und fröhliches Coden! 👩‍💻

Zurück zur Übersicht