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
- Funktions-Ausdruck
- Funktions-Konstruktor
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:
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.
- die innere (verschachtelte) Funktion kann nur über die äußere aufgerufen werden und ist für alle anderen Zugriffe unzugänglich
- die innere Funktion kann die Variablen und Parameter der äußeren nutzen
- die äußere Funktion kann die Variablen und Parameter der inneren Funktion nicht nutzen
- die innere Funktion wird als (lokale) quasi-Variable angesehen und kann von der äußeren Funktion aufgerufen werden
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
- Die Variable add ist der Rückgabewert einer Funktion die sich selbst aufgerufen hat
- Die Funktion läuft nur einmal, sie setzt den Zähler auf Null, und gibt ein Funktionsausdruck zurück
- Add wird auf diese Weise eine Funktion die auf die Variable counter zuzugreifen kann
- Das nennt man einen Kapselung (Closure), eine Funktion bekommt dabei sogenannte "private" Variablen
- Die Variable counter wird von außen geschützt und kann nur mit dem add-Funktion geändert werden
- 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
- Anstatt eines Selbstaufrufs wird diese Funktion einer globalen Variable "person" übergeben
- Der return der äußeren Funktion ist ein Objekt mit inneren Funktionen
- Dadurch bekommt die globale Variable Zugriff auf die Objekteigenschaften
- Der Parameter "name" ist im Prinzip nichts anderes als eine Variable der äußeren Funktion
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:
- decodeURI() (kodierten URI dekodieren)
- decodeURIComponent() (kodierten URI dekodieren - II)
- encodeURI() (URI kodieren)
- encodeURIComponent() (URI kodieren - II)
- eval() (Ausdruck interpretieren)
- isFinite() (auf numerischen Wertebereich prüfen)
- isNaN() (auf numerischen Wert prüfen)
- parseFloat() (in Kommazahl umwandeln)
- parseInt() (in Ganzzahl umwandeln)
Eine Referenz der objektunabhängigen Funktionen finden sie auf:
w3schools.com
wiki.selfhtml.org
developer.mozilla.org