Grundlagen: Javascript function – Funktionen

Javascript function – Funktionen Schritt für Schritt

Funktionen sind ein Block von Anweisungen mit einem Namen. Der Funktionsblock wird einmal definiert: Dann können die Javascript-Befehle der Funktion über den Namen mehrfach im Programm aufgerufen werden. Das Zusammenfassen von Befehlen in einer Funktion verbessert die Lesbarkeit des Scripts und verhindert Fehler.

23-02-02 SITEMAP

Javascript Funktionen sparen und strukturieren

In einer Programmiersprache ohne Funktionen müssten Anweisungen zigfach wiederholt werden, z.B. um Bilder in eine Slideshow zu laden.

const img1 = document.createElement("img");
img1.src = "apfelsine.jpg";
gallery.appendChild(img1);

const img2 = document.createElement("img");
img2.src = "kokos.jpg";
gallery.appendChild(img2);

Am Rande: Variablen mit const anstelle von var deklarieren: Ab IE11, Safari 11 – also in alleb modernen immergrünen Browser.

Ohne den Einsatz von Funktionen werden die Befehle eines Programme oder Skripte Zeile für Zeile durchgeführt. Hingegen überspringt der Javascript-Interpreter alle Anweisungen innerhalb einer Funktion, bis die Funktion mit ihrem Namen (gefolgt von runden Klammern) aufgerufen wird.

function buildGallery (gallery, src) {
  const img = document.createElement("img");
  img.src = src;
  gallery.appendChild (img);
}

buildGallery (gallery, "apfelsine.jpg");
buildGallery (gallery, "kokos.jpg");
buildGallery (gallery, "kiwi.jpg");

Function Hoisting

Es ist egal, ob im Scriptcode zuerst function buildGallery() und dann ihr Aufruf steht, oder ob der Funktionsaufruf vor der Definition der Funktion steht. Per Vorgabe schiebt Javascript alle Deklarationen von Funktionen »nach oben« (das nennt man function hoisting). Funktionen dürfen also aufgerufen werden, bevor sie definiert werden.

    +--- Schlüsselwort
    |       +---> Name der Funktion
    |       |
    |       |            +---> Parameter
    |       |            |       +---> Parameter
    |       |            |       |
function buildGallery (gallery, src) {
   const img = document.createElement("img");    // <-+
   img.src = src;                              //   +  Anweisungsblock
   gallery.appendChild (img);                  // <-+
}

    Argument ---+         +--- Argument
                |         |
                v         v
buildGallery (gallery, "apfelsine.jpg");        // Funktionsaufruf

Ablauf von Funktionen und Funktionsaufrufen

Der Javascript-Interpreter führt die Anweisungen im Block der Funktion also erst beim Funktionsaufruf buildGallery (gallery, "apfelsine.jpg"); aus.

Wenn die Funktion abgearbeitet ist, wird das Script mit der nächsten Anweisung nach dem Funktionsaufruf fortgesetzt.

Javascript Funktionen – Programmablauf
Funktionen werden übersprungen, bis sie aufgerufen werden

Gerade weil Funktionen in Javascript so fundamental sind, sind sie genial einfach und das Beispiel oben zeigt eigentlich schon alles, was man bei den ersten Schritten mit Javascript über Funktionen wirklich wissen muss.

Syntax von Funktionen

function machWas( param1, param2 ) {
    Anweisung;
    Anweisung; 
       …
    Anweisung;
}
  • Eine Funktion beginnt mit dem Schlüsselwort function gefolgt vom Namen der Funktion,
  • gefolgt von einem Paar runder Klammern mit den Parametern der Funktion.
  • Kommas trennen die Parameter der Funktion – wenn eine Funktion keine Parameter hat, bleibt die Klammer leer.
  • Die Anweisungen der Funktion stehen in einem Paar geschweifter Klammern.

Funktionsnamen dürfen genauso wie Variablennamen keine Leer- oder Sonderzeichen enthalten (nur der Unterstrich „_“ ist erlaubt) und sollten nicht länger als 32 Zeichen sein.

Am Ende des Funktionsblocks sollte ein return-Befehl stehen (muss aber nicht), um die Kontrolle wieder an die Stelle im Code zurück zu geben, von der aus die Funktion aufgerufen wurde. Das Schlüsselwort return kann ein Wert zurück geben – wenn die Funktion keine return-Anweisung oder return ohne einen Wert notiert, gibt die Funktion undefined zurück.

function changeStyle( obj, color ) {
   obj.style.color = color;
   obj.style.borderColor = color;
}

let elem = document.getElementById( 'myBlock' );
changeStyle( elem, "rot" );

Die Funktion changeStyle() benutzt keine return-Anweisung – der Javascript-Interpreter ersetzt die Anweisung changeStyle( elem, "rot" ); bei der Programmausführung einfach durch den Anweisungsblock der Funktion.

Variablen in Funktionen

Alle Variablen, die innerhalb einer Funktion mit var oder let vereinbart werden, sind nur innerhalb der Funktion bekannt und gültig. Was klingt wie eine Einschränkung, ist tatsächlich eine der wichtigsten Sicherungsmaßnahmen: So wird die Variable zu einer lokalen Variablen.

Wird in einer anderen Funktion eine Variable mit demselben Namen definiert, stören sich die Variablen nicht gegenseitig und können einander nicht überschreiben.

function paintBlue () {
    let color = "blue";
}

function changeStyle () {
    let color = 210;
}

Die beiden Variablen mit dem Namen color haben nicht denselben Gültigkeitsbereich oder Scope, in dem sie abgekapselt und sicher verwahrt sind.

Selbst wenn es eine globale Variable color oberhalb der Funktion gibt, ist die lokale Variable innerhalb ihrer Funktion sicher verpackt.

Color Scope
<div id="foo">
   <span id="color">Color</span> <span>Scope</span>
</div>
let color = "orange";

function paintBlue() {
    let color = "blue";
    document.getElementById("foo").setAttribute("style","color:" + color);
}
paintBlue();
document.getElementById("color").setAttribute("style","color:" + color );

Dieses Konzept trägt zur Fehlerreduzierung bei, so dass Libraries wie jQuery komplett in eine besondere Art von Funktion gekapselt werden: in sogen. self executing functions oder sofort selbstausführenden Funktionen.

In Javascript schränkten bis ES2015 nur Funktionen den Geltungsbereich von Variablen ein. Während in vielen Programmiersprachen Blöcke in geschweiften Klammern einen eingeschänkten Geltungsbereich für Variablen schaffen, war das in Javascript nicht der Fall, wenn das alte Schlüsselwort var benutzt wurde.

{
   var myGlobal;
}

war in Javascript eine globale Variable, die anderen Variablen mit demselben Namen überschreiben kann oder von Variablen mit demselben Namen überschrieben wird.

In älteren Versionen von Javascript hatten nur Funktionen einen Scope (abgeschirmten Geltungsbereich). Darum hat Javascript in den neusten Version zusätzlich zum Schlüsselwort var das Schlüsselwort let für die Definition von Variablen eingeführt: Variablen, die mit let definiert werden, gelten nur innerhalb ihres Blocks.

{
   const color = "Blau";
   let book;
}

Sowohl Konstante als auch let-Variablen gelten nur innerhalb des Blocks, der einfach durch die geschweiften Klammern erzeugt wird.

Funktionen aufrufen

Der Aufruf einer Funktion darf vor oder nach der Deklaration der Funktion stehen, aber die Argumente müssen vor dem Aufruf bekannt sein.

Im Funktionsaufruf stehen die Parameter in der Reihenfolge, in der sie bei der Deklaration der Funktion aufgeführt sind.

const autor = new Array( 'Thomas Mann', 'Neal Adams', 'Shakespeare' );
const title = new Array( 'Der Zauberberg', 'Batman', 'Sommernachtstraum' );

showBooks(         title,   autor,    2 );
                     |        |       |
function showBooks( myTitle, myAutor, num ) {
   let text = "";
   for (let i=0; i<num; i++) {
      text += myAutor[i] + ": " + myTitle[i] + "\r\n";
   }
   const list = document.getElementById( 'showBooks' );
   list.innerHTML = text; 
}


	

Das Skript deklariert zwei Arrays: autor und title mit je drei Elementen. Nach dem Aufruf showBooks( title, autor, 2 ); iteriert die Funktion durch die Arrays und listet die ersten beiden Buchtitel und ihre Autoren.

Die Parameter von von Javascript-Funktionen beschränken sich also nicht auf einfache Datentypen wie Zahlen oder Texte, sondern auch Arrays, Objekte und sogar Funktionen bilden reguläre Parameter.

Und noch ein Hinweis: Als locker typisierte Sprache prüft Javascript den Typ der Parameter nicht und überlässt es allein dem Programmierer, den Typ der Argumente sicher zu stellen.

Parameter und Argumente von Funktionen

Bei jedem Aufruf einer Funktion können unterschiedliche Argumente übergeben werden. In der Definition function name() { … } werden sie als Parameter in die runden Klammern hinter dem Namen der Funktion geschrieben. Parameter sind also Platzhalter für aktuelle Werte – die als Argumente bezeichnet werden.

In function summe (x, y) sind x und y Parameter, beim Aufruf summe (4,8) werden aktuelle Werte als Argument eingesetzt.

function summe(a, b, c) {}; // a, b, c sind Parameter

summen(1, 2, 3);            // 1, 2, 3 sind Argument

Die Parameter einer Javascript-Funktion sind eher eine unverbindliche Empfehlung.

  • Fehlende Parameter gelten als undefined und führen nicht zu einem Fehler.
  • Ein Funktionsaufruf kann mehr Argumente übergeben, als die Funktion erwartet.
function summe( x, y ) {
   let add = x + y;
   return add;
}

summe( 4, 5, 17 );   // gibt 9 zurück

summe( x, y ) addiert die ersten beiden Argumente und ignoriert den überflüssigen dritten Parameter. Cool – aber wozu soll das gut sein?

Auch wenn der Funktionsaufruf mehr Argumente notiert als die Deklaration, bietet Javascript einen Zugriff auf die überzähligen Argumente – allerdings nicht in der Form benannter Variablen.

Die Argumente einer JavaScript-Funktion sind in einem Objekt arguments organisiert. arguments[i] stellt einen alternativen Zugriff auf die Argumente zur Verfügung. Die Eigenschaft arguments.length gibt die Anzahl der Argumente zurück. Diese Technik birgt zusätzliche Flexibilität:

function mittel() {
   let summe = 0; 
   for (let i=0, j=arguments.length; i<j; i++) {
      summe += arguments[i];
   }
   return summe/arguments.length;
}

mittel( 15, 30, 50, 25 ); // gibt 30 zurück

Das Arguments-Objekt kann wie eine lokale Variable nur innerhalb der Funktion benutzt werden. Auch wenn arguments eine Eigenschaft length besitzt und ein Skript mit arguments[i] wie durch ein Array iteriert – arguments ist kein Array, sondern ein Objekt.

Wert von Argumenten ändern

Änderungen von Werten von Argumenten innerhalb einer Funktion haben keinen Einfluss auf den Wert des Arguments außerhalb der Funktion.

let betrag = 200;
let brutto = allInclusive( betrag );

function allInclusive( b ) {
   let mwst = b * 16 / 100;
   b = b + mwst;
   alert( "Betrag in allInclusive " + b );  // Hier ist b jetzt 232
   return b;
}

alert( "Betrag " + betrag + "\n" + "inkl. MwSt " + brutto );  
// Ausgabe:
// Betrag  200
// inkl. MwSt 232

Das Skript definiert eine Variable betrag mit dem Wert 200. Der Aufruf let brutto = allInclusive(betrag); verändert das Argument durch die Anweisung b = b + mwst; und die alert-Anweisung innerhalb der Funktion allInclusive gibt dementsprechend Betrag in allInclusive 232 aus.

Die alert-Anweisung am Ende des Skript-Fragments allerdings zeigt, dass der Funktionsaufruf die Variable betrag nicht geändert hat.

ES6: Default-Argumente

Mit ES6 können die Argumente von Funktionen einen Default-Wert annehmen. Dieser Vorgabewert wird in den runden Klammern der Funktion mit einem Gleichheitszeichen zugewiesen.

let addr = function (firstName="Peter", lastName="Schmitz") {
	console.log (firstName + " " + lastName);
}

addr();

Auch wenn ES6 in einem breiten Ausmaß von allen modernen Browsern unterstützt wird – dem sitzt immer noch IE11 gegenüber. ES6-Features erfordern den Einsatz eines Transpilers wie Babel.

Function Expression oder Funktionsausdruck

Funktionen lassen sich nicht nur durch die Schreibweise function abc () {} definieren. Das Ergebnis einer Funktion kann direkt einer Variablen zugewiesen werden.

let brutto = function (betrag, satz) {
   let mwst = betrag * satz / 100;
   let summe = betrag + mwst;
   return summe;
}

let summe = brutto (240, 19);
console.log ('Summe ' + summe);

Wenn eine Funktionen als function expression oder Funktions-Ausdruck geschrieben wird, kann sie erst aufgerufen werden, nachdem der Funktionsausdruck definiert wurde.

Diese Schreibweise wird auch als anonymer Funktionsausdruck oder anonymous function expression bezeichnet, weil die Funktion keinen Namen hat.

Named function expression – Funktionsaufruf mit Namen

Statt der Variablen eine anonyme Funktion zuzuweisen, kann die Funktion auch einen Namen haben.

let faktor = function computeFactorial (number) {
   if (number <= 1) {
      return 1;
   }
   return number * computeFactorial (number - 1 );
}

let result = faktor (5);
console.log ('Result ' + result);

Die Funktion berechnet die Fakultät einer Zahl (in der Mathematik als n! geschrieben). Die Fakultät ist das Produkt aller positiven Zahlen, die kleiner oder gleich der Zahl n sind und wird z.B. zur Berechnung von Permutationen herangezogen ( z.B. Wie kann ich 5 unterschiedliche Objekte in einer Reihe anordnen?).

Die Funktion hat jetzt zwar einen Namen, mit dem sie aufgerufen werden kann – allerdings nur innerhalb der Funktion selbst. Diese Schreibweise wird in erster Linie für rekursive Funktionen benutzt.