3 Funktionen
Funktionen sind eines der mächtigsten und komplexesten Sprachkonstrukte von JavaScript. Wie wir in den folgenden Kapiteln sehen werden, basieren sogar die Patterns für Klassen und Module auf Funktionen.
3.1 Bürger erster Klasse
Eine Funktion definiert ihr in JavaScript mit dem Schlüsselwortfunction. Dann folgen der Name der Funktion, Klammern für die deklarierten Parameter sowie ein Block für den Funktionskörper. Das Ganze könnte z.B. so aussehen:
function meineErsteFunktion() {
console.log("Toll!");
}
// Dazu der passende Aufruf:
meineErsteFunktion();
// => Toll!
Funktionen können auch anonym sein und haben dann keinen Namen. Das ist nur dann sinnvoll, wenn ihr sie direkt ausführt oder einer Variablen zuweist. Den Sinn der direkten Ausführung sehen wir weiter hinten in diesem Kapitel, hier erst einmal die Zuweisung an eine Variable:
var meineZweiteFunktion = function () {
console.log("Auch toll!");
};
meineZweiteFunktion();
// => Auch toll!
Vielleicht ist euch das Semikolon am Ende der Zuweisung aufgefallen? Ja, das Ganze ist nun zu einem Statement geworden, und Statements sollen ja laut Tipp aus dem letzten Kapitel mit einem Semikolon beendet werden.
Hinweis: Funktionen sind Objekte und können als solche einer Variablen zugewiesen oder als Parameter übergeben werden.
Hält eine Variable eine Referenz auf eine Funktion, ist die Funktion darüber mit dem ()-Operator aufrufbar.
3.2 Sichtbarkeitsbereiche (Scopes)
Wie in Kapitel 2 gesehen, spannen Blöcke in JavaScript im Gegensatz zu Java und vielen anderen Programmiersprachen keine Sichtbarkeitsbereiche auf. Zur kurzen Wiederholung: Hier gibt es zwar einen Block, allerdings ist auch nach Beendigung des Blocks die darin definierte Variablea noch sichtbar:
{
var a = 10;
}
// Hoppla!
console.log(a);
// => 10
Um Sichtbarkeitsbereiche zu definieren, gibt es in JavaScript ein anderes Konstrukt:
(function () {
var b = 10;
console.log("Noch bin ich da:" + b);
})();
console.log(typeof b);
// => undefined
Was passiert hier? Erst einmal definieren wir eine anonyme Funktion, also eine Funktion ohne Namen. Diese führen wir sofort mit () aus. Das weitere Klammerpaar um die Funktionsdefinition herum ist nur aus syntaktischen Gründen notwendig.
Da Funktionen Sichtbarkeitsbereiche aufspannen, ist die Variableb nach der Ausführung der Funktion nicht mehr sichtbar, und wir haben erreicht, was wir wollten. Dieses Pattern ist auch unter dem Namen IIFE fürImmediately-InvokedFunction Expression bekannt [1].
Manchmal sieht man das IIFE-Pattern mit einer leicht anderen Klammerung. Diese leicht andere Syntax ist jedoch äquivalent zu unserer Version oben:
(function () {
var b = 10;
console.log("Noch bin ich da:" + b);
}());
console.log(typeof b);
// => undefined
Sichtbarkeitsbereiche können beliebig tief geschachtelt werden. Aus jedem inneren Sichtbarkeitsbereich kommt ihr an alle Parameter und Variablen aller äußeren Sichtbarkeitsbereiche, nicht aber anders herum.
Ein bisschen mehr dazu könnt ihr in Kapitel 5 finden, in dem wir uns auch mit dem Konzept einerClosure beschäftigen. Hier erst einmal ein einfaches Beispiel für verschachtelte Sichtbarkeitsbereiche:
(function () {
var b = 10;
console.log(b); // => 10
(function () {
var c ="c";
console.log(c); // =>"c"
console.log(b); // => 10
})();
console.log(typeof c);
// => undefined
})();
3.3 Strict Mode
Beim Definieren von lokalen Variablen und Sichtbarkeitsbereichen kann man gerade als JavaScript-Anfänger viele Fehler machen. Hilfreich kann dabei der in ECMAScript5 eingeführte so genannte Strict Mode [2] sein. In diesem Modus gelten strengere Regeln für ein gültiges JavaScript-Programm.
Ihr könnt den Modus entweder für eine ganze Datei oder für einzelne Funktionen aktivieren. Dazu fügt ihr einen einfachen String mit dem Textstrict mode ein. Für eine ganze Datei schreibt man dies an deren Anfang, für eine Funktion als Erstes in den Körper der Funktion. So würde dann der Anfang jeder eurer JavaScript-Dateien aussehen:
"use strict";
// ... Hier kommt der eigentliche JavaScript-Inhalt
Und so würde die Aktivierung für eine einzelne Funktion aussehen:
function strikteFunktion() {
"use strict";
// ... Weiterer Funktionskörper
}
Was bewirkt der Modus nun? Fangen wir mit dem klassischen Beispiel an, das von JavaScript-Gegnern angeführt wird, um die Minderwertigkeit von JavaScript zu beweisen. Tatsächlich machen viele Programmierer aus einem Java-Umfeld diesen Fehler mindestens einmal. Der folgende Code ...
function aha() {
hugo = 10;
console.log(hugo);
}
aha();
// => 10
console.log(hugo);
// => 10
... tut, was er t