Funktionen

Ein JavaScript-Funktion ist ein Codeblock, der eine bestimmte Aufgabe erfüllt. JavaScript-Funktionen werden mit dem Schlüsselwort function eingeleitet, anschließend folgt ein benutzerdefinierter Bezeichner und der Parameter. Die Regeln für den Funktionsnamen (Bezeichner) sind dieselben wie bei Variablen. Funktionsparameter können auch Funktionsargumente beinhalten die mit Kommas getrennt werden. Die Anweisung der Funktion (Funktionsblock) wird in geschweiften Klammern eingeschlossen.

function foo() {
  var x = 5;
  var y = 6;
  var z = x + y;
  return z;
}

Rückgabewert mit return definieren

Der Rückgabewert einer Funktion kann mit der return-Anweisung bestimmt werden. Eine Funktion ohne return-Anweisung gibt als Wert undefined zurück. Eine Funktion kann mehrere return-Anweisungen haben, wird allerdings beim ersten Vorkommen abgebrochen und der aktuelle Wert wird an den Aufruf zurückgegeben. Eine return-Anweisung kann einzelne Werte, Objekte, Boolean und Funktionen zurückgeben.

Verwenden sie die Browser-Konsole um JavaScript Code auf dieser Seite zu testen.

Funktions-Syntax

JavaScript stellt drei Techniken für die Definition von Funktionen zur Verfügung:

Funktions-Deklaration

Wenn eine Funktion wie oben beschrieben, definiert wird, spricht man von einer Funktions-Deklaration. Wie schon erwähnt, konnen auch Funktionsparameter definiert sein, denen beim Aufruf ein Wert, sogenannte Funktionsargumente, zugewiesen wird.

function foo(arg1, arg2) {
  return arg1 + arg2;
}

foo(5, 6);

Den Parametern der Funktion kann auch ein Standardwert zugewiesen werden, falls das Argument nicht definiert wird. Allerdings hat dieses Beispiel bei meinen Tests nur in der Konsole von Firefox funktioniert.

function foo(arg1, arg2 = 6) {
  return arg1 + arg2;
}

foo(5);

Funktions-Ausdruck

Wenn die Funktion einer Variablen übergeben wird, spricht man von einem Funktions-Ausdruck. Die Variable kann dann wie der Funktionsname verwendet werden. Bei einem Funktionsausdruck braucht die Funktion selber keinen Funktionsnamen, muss aber mit einem Semikolon abgeschlossen werden.

var x = function(arg1, arg2) {
return arg1 + arg2;
};

x(5, 6);

Funktions-Konstruktor

Mit dem Schlüsselwort new wird der Funktions-Konstruktor eingeleitet. Diese Syntax wird im täglichen Gebrauch eher selten verwendet.
ACHTUNG: Der Funktions-Konstruktor verlangt eine andere Schreibweise.

  • Function beginnt mit einem Grossbuchstaben
  • Argumente und Anweisungen finden im Parameter statt
  • Argumente und Anweisungen werden in Anführungszeichen geschrieben (einfache oder doppelte)
  • Eine Funktion, die mit new erstellt wird braucht keinen Funktionsnamen
  • Die Anweisung wird mit Semikolon abgeschlossen
var x = new Function("arg1", "arg2", "return arg1 + arg2");

x(5,4);

Funktionsaufruf

Eine Funktion definieren heißt nicht, dass die Funktion irgendwas im Code bewirkt. Erst beim Aufruf wird der Inhalt des Funktionsblocks abgearbeitet. Für den Funktionsaufruf gibt es in JavaScript mehrere Möglichkeiten.

Möglichkeiten für den Funktionsaufruf

  • Mit dem Funktionsnamen und anschließenden Parametern // Funktionsname(arg1. arg2, ...)
  • Übergabe an eine Variable // Variablenname(arg1. arg2, ...)
  • Als Selbstaufruf // siehe Beispiel

Funktions-Selbstaufruf / Beispiel

Eine JavaScript-Funktion kann sich auch selbst aufrufen, dafür ist auch eine besonder Syntax notwendig.

  • Die Funktion braucht keinen Namen
  • Die Funktion wird in Klammern eingeschlossen
  • Am Ende wird einfach der Parameter gesetzt
  (function foo(arg1, arg2) {
  var arg3 = arg1 + arg2;
  return arg3;})(5,4);

Beispiele für einen Funktionsaufruf

function foo(arg1, arg2) {
return arg1 + arg2;
};

console.log(foo(5, 6));

// -----------------------------

var x = function(arg1, arg2) {
return arg1 + arg2;
};

console.log(x(5, 6));

// -----------------------------

var y = function(arg1, arg2) {
return arg1 + arg2;
};

var myFunc = y(5, 6);
console.log(myFunc);

// -----------------------------

var z = function(arg1, arg2) {
console.log(arg1 + arg2);
};

z(5, 6);

Funktions-Argumente

Funktions-Argumente werden im Parameter () definiert. Fehlende Argumente führen nicht zu einem Fehler, sie bekommen lediglich den Wert (undefined ).

function foo(arg1, arg2) {
  var arg3 = arg1 + arg2;
  return arg3;
}

foo("Hallo");

Auch zuviele Argumente führen zu keinem Fehler, sie werden einfach ignoriert.

function foo(arg1, arg2) {
  var arg3 = arg1 + arg2;
  return arg3;
}

foo(1, 2, 3);

Objekte als Parameter

Funktionsparameter können Primitives wie Strings, Numbers oder Boolean, aber auch Objekte wie z.B. benutzerdefinierte Objekte oder Arrays sein.

var x = ["Adi", "Prinz", 60];
function baz(myArray) {
return myArray[0];
}
console.log(baz(x)); // liefert Adi

var y = { firstName: "Adi", lastName: "Prinz", age: 60 };
function foo(myObject) {
return myObject.lastName;
}
console.log(foo(y)); // liefert Prinz

call by value

Bei der Übergabe einer Variablen an eine Funktion benutzt die Funktion den Wert der Variablen für Berechnungen. Selbst wenn der Variablen innerhalb der Funktion ein neuer Wert zugewiesen wird. Außerhalb der Funktion ändert sich der Wert der Variablen nicht. Diese Mimic wird als call by value bezeichnet, denn der Funktion wird nur der Wert der Variablen übergeben, nicht aber die Referenz auf die Speicherstelle.

function foo( arg ) {
   arg.val = 4000;
}
var myObject = new Object();
myObject.val = 2000; 

foo( myObject.val ); // das Argument entspricht dem Wert 2000
console.log(myObject.val); // liefert 2000

Das Argument myObject.val entspricht dem Wert 2000 und ist somit ein Primitive. Die primitiven Typen werden by value übergeben, aber ein Element vom Typ Object wird by reference übergeben, was soviel bedeutet wie:
Wenn eine Funktion eine Objekteigenschaft ändert, wird auch der gespeicherte Wert geändert!.

call by reference

Bei der Übergabe eines Objektes an eine Funktion wird das Objekt tatsächlich geändert und nicht einfach nur sein Wert in Berechnungen verwendet.

function foo( arg ) {
   arg.val = 4000;
}
var myObject = new Object();
myObject.val = 2000; 

foo( myObject ); // das Argument ist ein Objekt
console.log(myObject.val); // liefert 4000

In diesem Beispiel hat der Funktionsaufruf den Wert des Objektes verändert.

Weitere einfache Beispiele

// call by value
function foo( arg ) {
arg[0] = "Adi";
}
var myArray = new Array();
myArray[0] = "Gabi";

foo( myArray[0] ); // das Argument ist ein Objekt
console.log(myArray[0]); // liefert Gabi

// call by reference
function foo( arg ) {
arg[0] = "Adi";
}
var myArray = new Array();
myArray[0] = "Gabi";

foo( myArray ); // das Argument ist ein Objekt
console.log(myArray[0]); // liefert Adi

//----------------------------------------------

function foo(myObject) {
  myObject.firstName = "Gabi";
}
var person = { firstName: "Adi", lastName: "Prinz", age: 60 };
// call by value
foo(person.firstName); // Primitive: Adi
console.log(person.firstName); // liefert Adi
// call by reference
foo(person); // Objekt
console.log(person.firstName); // liefert Gabi            

Das arguments-Object

JavaScript Funktionen besitzen ein eingebautes Objekt mit dem Namen arguments. Das arguments-object beinhaltet ein Array der Argumente die beim Aufruf definiert sind. Das Arguments-Objekt kann nur innerhalb der Funktion benutzt werden.
ACHTUNG: Array-Zähler beginnt bei Null.

function foo(arg1, arg2) {
  return arguments[1];
}
foo(1, 2);

Die arguments.length-Eigenschaft

Das arguments-Object besitz auch ein length-Eigenschaft, welche die Anzahl der Argumente zurückgibt.

function foo(arg1, arg2) {
  return arguments.length;
}
foo(1, 2);

Funktionen sind Objekte

In JavaScript sind Funktionen immer auch Objekte. JavaScript-Objekte haben Eigenschaften und Methoden. Mit dem typeof-Operator kann man den Objekttyp feststellen.

var x= function(arg1, arg2) {
  var arg3 = arg1 + arg2;
  return arg3;
};

typeof x; // liefert function

Funktions-Methoden

JavaSript-Funktionen kennen auch zwei Methoden für den Funktionsaufruf:

  • call()
  • apply()

Beide Methoden benötigen einen Eigentümer (Owner Object) als erstes Argument. Dieser Eigentümer kann sowohl der Variablenname, als auch das Schlüsselwort this sein.

Funktionsaufruf mit call()

var x, y;
function myFunction(arg1, arg2) {
  var arg3 = arg1 + arg2;
  return arg3;
};
x = myFunction.call(x, 5, 4);
y = myFunction.call(this, 25, 14);
console.log(x);
console.log(y);

Das erste Argument der Methode ist der Eigentümer der Funktion (im Beispiel einmal mit x und einmal mit this). Weitere Argumente folgen wie gehabt.

Funktionsaufruf mit apply()

var x, y, myArray;
function myFunction(arg1, arg2) {
  var arg3 = arg1 + arg2;
  return arg3;
};
myArray = [5, 4];
x = myFunction.apply(x, myArray);
y = myFunction.apply(this, myArray);
console.log(x);
console.log(y);

apply() ist ähnlich wie call() nur die Funktionsargumente werden als Array übergeben.

Variablen-Scope (Sichtbarkeit)

Mit Scope ist die Gültigkeit oder Sichtbarkeit einer Variable gemeint. Variablen die innerhalb einer Funktion deklariert sind stehen nur innerhalb der Funktion zur Verfügung (local scope), es sei denn, die Deklaration erfolgt ohne dem Schlüsselwort var . Solche Variablen sind auch außerhalb der Funktion sichtbar (global scope) und stehen im gesamten Script zur Verfügung. Im Prinzip kann jede Variable ohne dem Schlüsselwort var deklariert werden.

x = "Hallo Welt!"; // Variable ist Global
var x = "Hallo Welt!"; // Variable ist Global

function myFunction(arg1, arg2) {
x = arg1 + arg2; // Variable ist Global
return x;
};

function myFunction(arg1, arg2) {
var x = arg1 + arg2; // Variable ist Local
return x;
};

Im Strict-Modus von JavaSript wird jede Variable, die ohne dem Schlüsselwort var deklariert wurde, einen Fehler verursachen. Für stabilen JavaScript-Code soll jede Variable mit dem Schlüsselwort var deklariert werden.

"use strict";
var x = "Hallo Welt!"; // Variable ist Global

var y = function(arg1, arg2) { // Variable ist Global
var z = arg1 + arg2; // Variable ist Local
return z;
};

console.log(x);
console.log(y(5,4));

Global-Scope & Funktionen

Globale Variablen sollen immer am Beginn des Quellcodes geschrieben werden. Lokale Variablen werden nicht sofort ausgeführt, sondern erst nachdem die Funktion aufgerufen wurde. Wenn eine Funktion als Funktions-Deklaration geschrieben wird, kann der Funktionsaufruf auch vor der Deklaration stehen.

var x = 5;
var y = 10;

myFunction();

function myFunction() {
  var z = x + y;
  console.log(z);
}

Hoisting (Hochziehen)

Wenn der Browser JavaScript interpretiert, werden alle deklarierten Variablen und Funktionen bei der Abarbeitung automatisch direkt am Anfang ausgeführt. Im vorigen Beispiel wurde der Funktionsaufruf vor der Funktions-Deklaration geschrieben. Sowas Ähnliches gibt es auch bei globalen Variablen:

Hoisting-Beispiel

"use strict";
x = "Hallo";
y = ["Adi", "Prinz", "Bad Hofgastein"];

console.log(x);
console.log(y[0]);
console.log(myFunction(x, y[0]));

var x;
var y;
function myFunction(a, b) {
var z = a + " " + b;
return z;
}

Im Beispiel werden den Variablen x und y Werte zugewiesen, die Variablendeklaration erfolg erst nach dem Aufruf. Im Klartext heißt das:
Wertzuweisungen können vor der Deklaration stattfinden, kennen aber kein Hoisting. Deklarationen können irgendwo im Quellcode geschrieben sein, Deklarationen werden hochgezogen (Hoisting).

Wesentlich übersichtlicher wird JavaScript-Code, wenn alle Variablen und Funktionen am Beginn deklariert werden, oder in einer externen Datei ausgelagert sind.

Nested-Functions (Verschachtelung)

Was in vielen Programmiersprachen nahezu undenkbar ist, kann in JavaSript vorkommen, nämlich verschachtelte Funktionen (Nested Functions). Nested bedeutet, dass Funktionen innerhalb von Funktionen geschrieben werden können.

function hypotenuse(a, b) {
function square(x) { 
return x * x; 
}
var y = Math.sqrt(square(a) + square(b));
console.log(y);
}
hypotenuse(3, 4);

Die Methode Math.sqrt() erwartet als Parameter eine Zahl, und liefert die Quadratwurzel dieser Zahl zurück.

Rekursionen

Rekursion ist eine Programmiertechnik in JavaScript, bei der sich eine Funktion selbst aufruft. Es gibt drei Möglichkeiten für eine Funktion, um sich selbst aufzurufen.

  • mit dem Funktionsnamen
  • eine Variable mit Referenz zur Funktion
  • arguments.callee
// mit dem Funktionsnamen
var foo = function bar() {
   bar();
};

// mit dem Variablennamen
var foo = function bar() {
   foo();
};

// arguments.callee
var foo = function bar() {
   arguments.callee();
};

Innerhalb des Funktionskörper, sind die drei Anweisungen äquivalent und machen dasselbe.

arguments.callee

callee ist eine Eigenschaft des arguments-Objekt. Es kann benutzt werden, um die Funktion im Funktionskörper aufzurufen.
ACHTUNG: arguments.callee gilt als veraltert und darf im Strict-Modus von JavaScript nicht mehr verwendet werden.

Beispiel einer rekursiven Funktion

Die äußere loop-Funktion prüft den Wert x, die innere loop-Funktion incrementiert den Wert x. Der Wert x wird beim Aufruf au Null (0) gestellt. Die Werte x werden rekursiv in der Browser-Konsole zurückgegeben.

function loop(x) {
if (x >= 10) {
return;
}
loop(x + 1); // the recursive call
console.log(x);
}
loop(0);

Closure (Kapselung)

JavaScript ermöglicht die Verschachtelung von Funktionen und gewährt der inneren Funktion vollen Zugriff auf alle Variablen und Funktionen der äußeren Funktion.
Die äußere Funktion hat keinen Zugriff auf die in der inneren Funktion definierten Variablen und Funktionen. Dies liefert eine Art von Sicherheit für die Variablen der inneren Funktion. Die Lebensdauer einer globalen Variablen besteht, solange das Script (HTML-Dokument) geöffnet ist.
Die Lebensdauer einer lokalen Variablen besteht nur für den Zeitraum des Funktionsaufrufs und wird danach aus dem Arbeitsspeicher wieder gelöscht.
Da die innere Funktion Zugriff auf den Umfang der äußeren Funktion hat, können die in der äußeren Funktion definierten Variablen und Funktionen länger Leben als die äußere Funktion selbst. Wenn die innere Funktion es schafft, länger zu Leben als die äußere Funktion, spricht man von Kapselung bzw. Closure.

Beispiel für einen Zähler

var add = (function () {
var counter = 0;
return function () {
return counter += 1;
}
})();

console.log(add()); // liefert 1
console.log(add()); // liefert 2
console.log(add()); // liefert 3
  1. Die Variable add ist der Rückgabewert einer Funktion die sich selbst aufgerufen hat
  2. Die Funktion läuft nur einmal, sie setzt den Zähler auf Null, und gibt ein Funktionsausdruck zurück
  3. Add wird auf diese Weise eine Funktion die auf die Variable counter zuzugreifen kann
  4. Das nennt man einen Kapselung (Closure), eine Funktion bekommt dabei sogenannte "private" Variablen
  5. Die Variable counter wird von außen geschützt und kann nur mit dem add-Funktion geändert werden
  6. Eine Kapselung ist eine innere Funktion die es schafft, länger zu Leben als die äußere Funktion

Beispiel für ein Passwort

var getCode = (function(){
  var secureCode = "OAxy#12"; // Variable ohne Zugriff von Außen (nicht Änderbar)
  
  return function () {
    return secureCode;
  };
})();

console.log(getCode()); // liefert secureCode

Noch ein Beispiel

function createPerson(name) {
  var gender;
  
  return {
    setName: function(newName) {
      name = newName;
    },
    
    getName: function() {
      return name;
    },
    
    getGender: function() {
      return gender;
    },
    
    setGender: function(newGender) {
        gender = newGender;
    }
  }
}

var person = createPerson("Adi");
console.log(person.getName()); // liefert Adi

person.setName("Julia");
person.setGender("female");
console.log(person.getGender()); // liefert female
console.log(person.getName()); // liefert Julia

Objektunabhängige Funktionen

Neben den selbstdefierten Funktionen gibt es in JavaScript noch objektabhängige- und objektunabhängige-Funktionen. Selbstdefierten Funktionen wurden in diesem Script vorgestellt, objektabhängige-Funktionen werden im Kapitel Browser-Objekte behandelt und objektunabhängige-Funktionen finden sie in dieser Liste:

Eine Referenz der objektunabhängigen Funktionen finden sie auf:

w3schools.com

wiki.selfhtml.org

developer.mozilla.org