JavaScript/Tutorials/Einstieg/Funktionen

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Informationen zu diesem Text

Lesedauer
45min
Schwierigkeitsgrad
einfach
Vorausgesetztes Wissen
keine

Wenn die Programme länger und komplexer werden, macht eine klare Programmstruktur die Fehlersuche deutlich einfacher.

In diesem Kapitel lernen Sie, wie Sie monolithische Konstruktionen mit unübersichtlichem Spaghetticode vermeiden und die verschiedenen Aufgaben Ihres Programms stattdessen auf relativ kurze und gut überschaubare Unterprogramme (in JavaScript Funktionen genannt) gliedern, wobei dann auch nicht mit Kommentaren gespart werden sollte.

Funktionen[Bearbeiten]

Funktionen helfen Programmierern, einzelnen Programmteilen einen Namen zu geben und diese mehrfach wiederzuverwenden.

Das Grundprinzip ist leicht:

  1. Das gesamte Programm wird in einzelne Aufgaben zerlegt.
  2. Die einzelnen Schritte dieser Aufgabe werden in einer Funktion notiert.
  3. Diese Funktion wird aufgerufen. Dabei kann sie unterschiedliche Parameter enthalten. Die Funktion erfüllt anhand der Parameter eine bestimmte Aufgabe und gibt das Ergebnis zurück. Je nach Parameter wird die Funktion üblicherweise auch andere Resultate liefern.
Aufbau einer Funktion
function funktionsname(Parameterliste) {
  // Anweisungen
}

Jede Funktion hat einen Namen, eine Parameterliste und einen Rückgabewert. Die Parameter sind Eingabewerte für die Funktion. Sie stehen innerhalb der Funktion als Variablen zur Verfügung. Das heißt, dass man über die Parameter Daten in die Funktion hineingibt, in der Funktion dann verarbeitet und das Verarbeitungsergebnis dann über den Rückgabewert an den Aufrufer der Funktion zurückgibt.

Betrachten wir hierzu ein Beispiel, das Ziehen der Quadratwurzel:

9. Funktion WurzelZiehen ansehen …
'use strict';
var eingabe,
    ergebnis,
    text;

  function wurzelZiehen(zahl) {
    // Hilfsfunktion, die Wurzel aus übergebener 'zahl' zieht und als 'ergebnis' zurückgibt
    zahl = parseFloat(zahl);
    ergebnis = Math.sqrt(zahl);
    return ergebnis;
  }
 
  eingabe = prompt('Bitte geben Sie eine Zahl ein!', eingabe);
 
  wurzelZiehen(eingabe);
  text = `Die Wurzel von ${eingabe} ist ${ergebnis}.`;
  console.log(text);
Nachdem die Variablen deklariert wurden, wird eine Funktion wurzelZiehen() erzeugt, aber nicht ausgeführt.

Die geschweiften Klammern kennzeichnen Start und Ende des Anweisungsblocks.
Damit bei einer Eingabe eines Buchstabens oder ähnlichem keine Fehlermeldung NaN ausgeworfen wird, wird die übergebene Variable überprüft und, wenn nötig mit parseFloat passend formatiert.
Die Funktion zieht mit Math.sqrt() die Wurzel aus der übergebenen Zahl und weist sie der Variablen ergebnis zu. Der Rückgabewert der Funktion ist die Variable ergebnis und wird durch das Schlüsselwort return gekennzeichnet. Mit diesem Befehl wird die Funktion also beendet und gleichzeitig der Inhalt von ergebnis an den Aufrufer von wurzelZiehen zurückgegeben.

Wenn eine Zahl eingabe eingegeben wird, wird die Funktion wurzelZiehen(eingabe); aufgerufen und ihr die Variable eingabe übergeben. Der Rückgabewert wird in der Variablen ergebnis abgelegt. Dieses wird dann wieder ausgegeben.
Beachten Sie: Die Überprüfung der Eingabe mit parseFloat sollte schon bei der Eingabe erfolgen, sodass an die Funktion wurzelZiehen nur gültige Zahlen übergeben werden. Aus Gründen der Einfachheit wurde hier auf eine solche Schleife verzichtet.
In einer normalen Webseite kann durch die Verwendung von input type="number" sichergestellt werden, dass nur Zahlen eingegeben werden können.

Wie Sie sicherlich gesehen haben, entstehen beim Wurzelziehen nur in den seltensten Fällen ganze Zahlen. Da die Dezimalzahlen nicht besonders ansehnlich sind, können Sie sie auch runden:

10. Runden einer Zahl ansehen …
'use strict';
  var eingabe,
      ergebnis,
      gerundet,
      text;
  
  //Helferfunktionen
  function wurzelZiehen(zahl) {
    ergebnis = Math.sqrt(zahl); 
    runden(ergebnis); 
    return gerundet;
  }
  
  function runden(zahl) {
    gerundet = zahl.toFixed(2);
    return gerundet;
  }
	  
  eingabe = prompt('Bitte geben Sie eine Zahl ein!', eingabe);
  eingabe = parseFloat(eingabe);	
  if (isNaN(eingabe)) {
    alert(`Der eingebenene Wert:${eingabe} ist keine Zahl!`);
  }
  
  wurzelZiehen(eingabe);
  text = `Die Wurzel von ${eingabe} ist ${ergebnis}, gerundet: ${gerundet}.`;
  console.log(text);
Direkt nach der Eingabe wird die erhaltene Variable überprüft und, wenn nötig mit parseFloat passend formatiert.

In einer Abfrage wird überprüft, ob die Variable ungültig ist. Wenn das der Fall ist, wird eine Fehlermeldung mit alert() ausgegeben.
Die Funktion wurzelZiehen() ruft nach der Berechnung die Funktion runden() auf und übergibt ihr die Variable ergebnis.
Anschließend wird die Zahl mit toFixed(2) auf 2 Nachkommastellen gekürzt und der Variablen gerundet übergeben, die als Rückgabewert zurückgegeben wird.

Anschließend werden sowohl das genaue Ergebnis als auch die gerundete Zahl ausgegeben.
Empfehlung:
Programmieren Sie Funktionen so allgemein wie möglich, damit Sie sie mehrfach und unter möglichst verschiedenen Bedingungen einsetzen können.

Vorteile einer solchen Programmierung nach dem Grundsatz DRY (Don't repeat yourself!) sind:

  • kürzere Programme
  • bessere Lesbarkeit von Programmcode
  • ein besser zu wartender Code bei künftigen Überarbeitungen

Im Laufe der Zeit sammelt sich so eine Bibliothek an wiederverwendbaren Helfer-Funktionen, die Ihnen viel Arbeit sparen.

Debuggen mit Haltepunkten[Bearbeiten]

Durch die im vorherigen Kapitel aufgeführten Kontrollausgaben können Sie den Ablauf eines Scriptes nachvollziehen und Variablen ausgeben, um deren Werte zu prüfen. Selbst minifizierter Code kann wieder lesbar formatiert werden.

Ist Ihnen rechts neben der Konsole der Debugger (Überwachen) aufgefallen? Er ist ein vielseitiges und mächtiges Werkzeug, mit dem Sie die Funktionsweise eines Scriptes komfortabler untersuchen können, denn Sie müssen nicht nach jeder Anweisung eine Kontrollausgabe einfügen. Ein JavaScript-Debugger bietet im Allgemeinen folgende Möglichkeiten:

Setzen von Haltepunkten[Bearbeiten]

Sie können Haltepunkte (englisch Breakpoints) setzen, indem sie in der Konsole im Quelltext erst oben links auf das Symbol klicken und dann die einzelnen Zeilennummern markieren. Die Ausführung des JavaScripts wird an dieser Stelle unterbrochen und Sie können alle Variablen und Objekte rechts im Debugger sehen und überprüfen.

Screenshot

Mit einem Klick auf den aktuellen Haltepunkt, der nun ein Play-Symbol beinhaltet, können Sie das Script von dieser Code-Zeile aus wieder zum Laufen bringen und die folgenden Anweisungen nun Schritt für Schritt ausführen, Anweisungen überspringen und aus aufgerufenen Funktionen herausspringen. Bei dieser schrittweisen Ausführung können Sie überprüfen, welche Werte bestimmte Objekte und Variablen an dieser Stelle im Script haben.


Call Stack[Bearbeiten]

Bei komplerexen Programmen mit mehreren Funktionen, die sich gegenseitig aufrufen, hilft Ihnen ein Debugger, die Übersicht über das Aufrufen und Abarbeiten von Funktionen zu behalten. In der Einzelschritt-Ausführung haben Sie den sogenannten Call Stack (englisch für Aufruf-Stapel) im Blick. Das ist die Verschachtelung der Funktionen, die gerade abgearbeitet werden. Wenn beispeilsweise die Funktion a die Funktion b aufruft und diese wiederum die Funktion c, so ist der Stapel a > b > c. Die Funktion c, die gerade ausgeführt wird, liegt sozusagen oben auf dem Stapel. Nach dessen Ausführung wird c vom Stapel genommen und in die Funktion b zurückgekehrt - und so weiter.

Exkurs: Objekte[Bearbeiten]

Objekte helfen Programmierern, Daten strukturiert handzuhaben und sogar Programme in sinnvolle Teilbereiche zu untergliedern. Man stelle sich einen Datensatz zu einer Bestellung oder eine Spielfigur in einem Browser-Game vor, in beiden Fällen benötigt man ein passendes Objekt. Objekte können in JavaScript sehr vielfältig gestaltet sein, je nach Zweck des Programmierers.

Objektliteral
var data = {
  id : "17283",
  firstName : "Hans",
  name : "Meier",
  type : "Bestellung",
  items : [2231, 188832, 231231, 3123, 123]
}
In diesem Objektliteral ist die Datenstruktur eines einfachen Datensatzes wie z.B. für eine Bestellung in einem Webshop abgebildet.

Das obige Beispiel definiert ein ganzes Objekt. Man kann auch durch eine Reihe von Anweisungen ein solches Objekt erstellen:

Objekt dynamisch erstellt
var data = new Object();

data.id = "17283";
data.firstName = "Hans";
data.name = "Meier";
data.type = "Bestellung";
data.items = [2231, 188832, 231231, 3123, 123];
Das Objekt data wird zunächst als leeres Objekt instanziiert. Anschließend werden ihm seine Eigenschaften zugewiesen. Das Ergebnis ist das gleiche, wie im obigen Beispiel, nur auf andere Weise erstellt.