Funktionen — wiederverwendbare Codeblöcke
Ein weiteres grundlegendes Konzept in der Programmierung sind Funktionen, die es Ihnen ermöglichen, einen Codeabschnitt, der eine einzelne Aufgabe ausführt, in einem definierten Block zu speichern und dann diesen Code nach Bedarf mit einem einzigen kurzen Befehl aufzurufen — anstatt denselben Code mehrmals eintippen zu müssen. In diesem Artikel werden wir grundlegende Konzepte von Funktionen untersuchen, wie zum Beispiel die grundlegende Syntax, wie man sie aufruft und definiert, Geltungsbereich und Parameter.
| Voraussetzungen: | Ein Verständnis von HTML und den Grundlagen von CSS, Vertrautheit mit den JavaScript-Grundlagen, wie sie in den vorhergehenden Lektionen behandelt wurden. |
|---|---|
| Lernziele: |
|
Wo finde ich Funktionen?
In JavaScript finden Sie Funktionen überall. Tatsächlich haben wir Funktionen im gesamten Kurs bisher verwendet, wir haben jedoch nicht viel darüber gesprochen. Jetzt ist es an der Zeit, dass wir anfangen, explizit über Funktionen zu sprechen und ihre Syntax zu erkunden.
Im Grunde genommen, wann immer Sie eine JavaScript-Struktur verwenden, die ein Paar Klammern — () — enthält, und Sie nicht eine häufige Sprachstruktur wie eine for-Schleife, while- oder do...while-Schleife oder if...else-Anweisung verwenden, nutzen Sie eine Funktion.
Eingebaute Browser-Funktionen
Wir haben in diesem Kurs eingehend eingebaute Browser-Funktionen verwendet.
Jedes Mal, wenn wir eine Textzeichenfolge manipulierten, zum Beispiel:
const myText = "I am a string";
const newString = myText.replace("string", "sausage");
console.log(newString);
// the replace() string function takes a source string,
// and a target string and replaces the source string,
// with the target string, and returns the newly formed string
Oder jedes Mal, wenn wir ein Array manipulierten:
const myArray = ["I", "love", "chocolate", "frogs"];
const madeAString = myArray.join(" ");
console.log(madeAString);
// the join() function takes an array, joins
// all the array items together into a single
// string, and returns this new string
Oder jedes Mal, wenn wir eine Zufallszahl generierten:
const myNumber = Math.random();
// the random() function generates a random number between
// 0 and up to but not including 1, and returns that number
Wir haben eine Funktion genutzt!
Hinweis: Fühlen Sie sich frei, diese Zeilen in die JavaScript-Konsole Ihres Browsers einzugeben, um sich bei Bedarf mit ihrer Funktionalität vertraut zu machen.
Die JavaScript-Sprache bietet viele eingebaute Funktionen, die es Ihnen ermöglichen, nützliche Dinge zu tun, ohne all diesen Code selbst schreiben zu müssen. Tatsächlich könnte ein Teil des Codes, den Sie aufrufen, wenn Sie eine eingebaute Browserfunktion aufrufen (ein schicker Ausdruck für ausführen), nicht in JavaScript geschrieben werden — viele dieser Funktionen rufen Teile des Hintergrund-Codes des Browsers auf, der größtenteils in systemnahen Sprachen wie C++ und nicht in Web-Sprachen wie JavaScript geschrieben ist.
Beachten Sie, dass einige eingebaute Browserfunktionen nicht Teil der Kern-JavaScript-Sprache sind — einige sind Teil von Browser-APIs, die auf der Standardsprache aufbauen, um noch mehr Funktionalität zu bieten (siehe diesen frühen Abschnitt unseres Kurses für weitere Beschreibungen). Wir werden die Verwendung von Browser-APIs in einem späteren Modul genauer betrachten.
Funktionen versus Methoden
Funktionen, die Teil von Objekten sind, werden Methoden genannt; Sie werden später im Modul über Objekte lernen. Vorerst wollten wir nur mögliche Verwirrung über Methoden im Gegensatz zu Funktionen beseitigen — es ist wahrscheinlich, dass Sie auf beide Begriffe stoßen werden, wenn Sie verwandte Ressourcen im Web betrachten.
Der eingebaute Code, den wir bisher verwendet haben, kommt in beiden Formen: Funktionen und Methoden. Sie können die vollständige Liste der eingebauten Funktionen sowie der eingebauten Objekte und ihrer entsprechenden Methoden in unserem JavaScript-Referenz überprüfen.
Sie haben auch schon viele benutzerdefinierte Funktionen im Kurs gesehen — Funktionen, die in Ihrem Code definiert sind, nicht im Browser. Jedes Mal, wenn Sie einen benutzerdefinierten Namen mit Klammern direkt danach gesehen haben, haben Sie eine benutzerdefinierte Funktion verwendet. In unserem random-canvas-circles.html Beispiel (siehe auch den vollständigen Quellcode) aus unserem Schleifenartikel haben wir eine benutzerdefinierte draw() Funktion eingebaut, die folgendermaßen aussieht:
function draw() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (let i = 0; i < 100; i++) {
ctx.beginPath();
ctx.fillStyle = "rgb(255 0 0 / 50%)";
ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
ctx.fill();
}
}
Diese Funktion zeichnet 100 zufällige Kreise innerhalb eines <canvas>-Elements. Jedes Mal, wenn wir das tun wollen, können wir die Funktion so aufrufen, anstatt den gesamten Code jedes Mal erneut schreiben zu müssen:
draw();
Funktionen können jeden beliebigen Code enthalten, sogar andere Funktionsaufrufe. Zum Beispiel ruft die oben gesehene draw() Funktion die random() Funktion dreimal auf; random() wird durch den folgenden Code definiert:
function random(number) {
return Math.floor(Math.random() * number);
}
Wir benötigten diese Funktion, weil die im Browser eingebaute Math.random() Funktion nur eine zufällige Dezimalzahl zwischen 0 und 1 generiert. Wir wollten eine zufällige Ganzzahl zwischen 0 und einer bestimmten Zahl.
Funktionen aufrufen
Wahrscheinlich ist Ihnen dies inzwischen klar, aber nur für den Fall: Um eine Funktion nach ihrer Definition tatsächlich zu verwenden, müssen Sie sie ausführen — oder aufrufen. Dies geschieht, indem Sie irgendwo im Code den Namen der Funktion angeben, gefolgt von Klammern.
function myFunction() {
alert("hello");
}
myFunction();
// calls the function once
Hinweis: Diese Form der Funktionserstellung wird auch als Funktionsdeklaration bezeichnet. Sie wird immer höhergestuft, was bedeutet, dass Sie die Funktion über ihrer Definition aufrufen können und sie trotzdem funktioniert.
Funktionsargumente und -parameter
Einige Funktionen erfordern Argumente, wenn Sie sie aufrufen — Werte, die in die Klammern der Funktion aufgenommen werden müssen, damit die Funktion ihre Aufgabe ordnungsgemäß ausführen kann.
Sie werden auch den Begriff Parameter hören, oft austauschbar mit Argumenten. Dies ist in informellen Diskussionen oft in Ordnung, aber sie haben unterschiedliche Bedeutungen. Parameter sind die Variablen, die in einer Funktionsdefinition aufgelistet sind, während Argumente die Werte sind, die an die Funktion übergeben werden, um die Parameter darzustellen, wenn die Funktion aufgerufen wird.
Schauen wir uns einige Beispiele an. Die Math.random() Funktion benötigt keine Argumente. Beim Aufruf gibt sie immer eine zufällige Zahl zwischen 0 und 1 zurück:
const myNumber = Math.random();
Die Zeichenkette replace() Funktion benötigt jedoch zwei Argumente — die Teilzeichenfolge, die in der Hauptzeichenfolge gefunden werden soll, und die Teilzeichenfolge, durch die diese Zeichenfolge ersetzt werden soll:
const myText = "I am a string";
const newString = myText.replace("string", "sausage");
Hinweis: Wenn Sie mehrere Parameter oder Argumente angeben müssen, trennen Sie diese durch Kommata.
Optionale Parameter
Manchmal sind Parameter als optional definiert — Sie müssen beim Aufrufen der Funktion keine äquivalenten Argumente angeben. Wenn Sie dies nicht tun, verwendet die Funktion in der Regel einen Standardwert. Zum Beispiel ist der Parameter der Array join() Funktion optional:
const myArray = ["I", "love", "chocolate", "frogs"];
const madeAString = myArray.join(" ");
console.log(madeAString);
// returns 'I love chocolate frogs'
const madeAnotherString = myArray.join();
console.log(madeAnotherString);
// returns 'I,love,chocolate,frogs'
Wenn kein Argument enthalten ist, um ein Verknüpfungs-/Trennzeichen anzugeben, wird standardmäßig ein Komma verwendet.
Standardparameter
Wenn Sie eine Funktion schreiben und optionale Parameter definieren möchten, können Sie Standardwerte festlegen, indem Sie = nach dem Namen des Parameters hinzufügen, gefolgt vom Standardwert:
function hello(name = "Chris") {
console.log(`Hello ${name}!`);
}
hello("Ari"); // Hello Ari!
hello(); // Hello Chris!
Anonyme Funktionen und Pfeilfunktionen
Bisher haben wir Funktionen folgendermaßen erstellt:
function myFunction() {
alert("hello");
}
Aber Sie können auch eine Funktion erstellen, die keinen Namen hat:
(function () {
alert("hello");
});
Dies wird als anonyme Funktion bezeichnet, da sie keinen Namen hat. Sie werden häufig anonyme Funktionen sehen, wenn eine Funktion erwartet, eine andere Funktion als Argument zu erhalten. In diesem Fall wird oft eine anonyme Funktion als Argument übergeben.
Hinweis: Diese Form der Funktionserstellung wird auch als Funktionsausdruck bezeichnet. Im Gegensatz zu Funktionsdeklarationen werden Funktionsausdrücke nicht höhergestuft.
Beispiel einer anonymen Funktion
Angenommen, Sie möchten Code ausführen, wenn der Benutzer in ein Textfeld tippt. Dazu können Sie die addEventListener() Funktion des Textfelds aufrufen. Diese Funktion erwartet mindestens zwei Argumente:
- Der Name des Ereignisses, auf das gewartet werden soll, in diesem Fall ist das
keydown - Eine Funktion, die ausgeführt wird, wenn das Ereignis eintritt.
Wenn der Benutzer eine Taste drückt, ruft der Browser die von Ihnen bereitgestellte Funktion auf und übergibt ihr einen Parameter mit Informationen zu diesem Ereignis, einschließlich der bestimmten Taste, die der Benutzer gedrückt hat:
function logKey(event) {
console.log(`You pressed "${event.key}".`);
}
textBox.addEventListener("keydown", logKey);
Anstatt eine separate logKey() Funktion zu definieren, können Sie eine anonyme Funktion in addEventListener() übergeben:
textBox.addEventListener("keydown", function (event) {
console.log(`You pressed "${event.key}".`);
});
Pfeilfunktionen
Wenn Sie eine anonyme Funktion auf diese Weise übergeben, gibt es eine alternative Form, die als Pfeilfunktion bezeichnet wird. Anstatt function(event), schreiben Sie (event) =>:
textBox.addEventListener("keydown", (event) => {
console.log(`You pressed "${event.key}".`);
});
Wenn die Funktion nur ein Argument hat, können Sie die Klammern darum weglassen:
textBox.addEventListener("keydown", event => {
console.log(`You pressed "${event.key}".`);
});
Schließlich, wenn Ihre Funktion nur eine einzelne Zeile enthält, die eine return-Anweisung ist, können Sie die geschweiften Klammern und das return-Schlüsselwort weglassen und den Ausdruck implizit zurückgeben. Im folgenden Beispiel verwenden wir die map() Methode von Array, um jeden Wert im ursprünglichen Array zu verdoppeln:
const originals = [1, 2, 3];
const doubled = originals.map(item => item * 2);
console.log(doubled); // [2, 4, 6]
Die map() Methode übergibt jedes Element im Array an die gegebene Funktion, nimmt dann den Rückgabewert der Funktion und fügt ihn einem neuen Array hinzu.
Die Pfeilfunktion ist sehr prägnant; das Umschreiben unseres map() Codes zur Verwendung einer regulären anonymen Callback-Funktion würde so aussehen:
const doubled = originals.map(function (item) {
return item * 2;
});
Sie können dieselbe prägnante Pfeilfunktionssyntax verwenden, um das addEventListener() Beispiel neu zu schreiben:
textBox.addEventListener("keydown", (event) =>
console.log(`You pressed "${event.key}".`)
);
In diesem Fall wird der Wert von console.log(), der undefined ist, implizit von der Callback-Funktion zurückgegeben.
Wir empfehlen die Verwendung von Pfeilfunktionen, da sie Ihren Code kürzer und lesbarer machen können. Um mehr zu erfahren, siehe den Abschnitt über Pfeilfunktionen im JavaScript-Leitfaden und unsere Referenzseite zu Pfeilfunktionen.
Hinweis: Es gibt einige subtile Unterschiede zwischen Pfeilfunktionen und normalen Funktionen. Sie liegen außerhalb des Umfangs dieses Einführungstutorials und werden in den hier besprochenen Fällen wahrscheinlich keinen Unterschied machen. Um mehr zu erfahren, siehe die Referenzdokumentation zu Pfeilfunktionen.
Live-Beispiel für Pfeilfunktion
Hier ist eine vollständige funktionierende Version des keydown Beispiels, das wir oben besprochen haben:
Das HTML:
<input id="textBox" type="text" />
<div id="output"></div>
Das JavaScript:
const textBox = document.querySelector("#textBox");
const output = document.querySelector("#output");
textBox.addEventListener("keydown", (event) => {
output.textContent = `You pressed "${event.key}".`;
});
Das Ergebnis - versuchen Sie, in das Textfeld zu tippen, und sehen Sie sich die Ausgabe an:
Funktionsbereich und Konflikte
Sprechen wir ein wenig über den Geltungsbereich — ein wichtiges Konzept im Umgang mit Funktionen. Wenn Sie eine Funktion erstellen, sind die innerhalb der Funktion definierten Variablen und andere Dinge in ihrem eigenen separaten Bereich. Das bedeutet, dass sie in ihrem eigenen abgetrennten Bereich eingeschlossen sind und von außerhalb der Funktion nicht erreicht werden können.
Der oberste Bereich außerhalb all Ihrer Funktionen wird als globaler Bereich bezeichnet. Werte, die im globalen Bereich definiert sind, sind überall im Code zugänglich.
JavaScript funktioniert so, hauptsächlich aus Sicherheits- und Organisationsgründen. Manchmal möchten Sie nicht, dass Variablen von überall im Code zugänglich sind. Externe Skripte, die von woanders aufgerufen werden, könnten Ihren Code durcheinander bringen und Probleme verursachen, wenn sie dieselben Variablennamen verwenden, was zu Konflikten führen könnte. Dies könnte absichtlich oder einfach zufällig geschehen.
Angenommen, Sie haben eine HTML-Datei, die zwei externe JavaScript-Dateien referenziert, und beide haben eine Variable und eine Funktion definiert, die denselben Namen verwenden:
<!-- Excerpt from the HTML -->
<script src="first.js"></script>
<script src="second.js"></script>
<script>
greeting();
</script>
// first.js
const name = "Chris";
function greeting() {
alert(`Hello ${name}: welcome to our company.`);
}
// second.js
const name = "Zaptec";
function greeting() {
alert(`Our company is called ${name}.`);
}
Sie können dieses Beispiel live auf GitHub laufen sehen (siehe auch den Quellcode). Laden Sie es in einem separaten Browser-Tab, bevor Sie die folgende Erklärung lesen.
-
Wenn das Beispiel in einem Browser gerendert wird, sehen Sie zuerst ein Alert-Fenster, das
Hello Chris: welcome to our company.anzeigt, was bedeutet, dass diegreeting()Funktion, die im ersten Skript definiert ist, durch dengreeting()Aufruf im internen Skript aufgerufen wurde. -
Das zweite Skript wird jedoch überhaupt nicht geladen und ausgeführt, und im Konsolenprotokoll wird ein Fehler ausgegeben:
Uncaught SyntaxError: Identifier 'name' has already been declared. Dies liegt daran, dass dienameKonstante bereits infirst.jsdeklariert ist, und Sie können dieselbe Konstante nicht zweimal im selben Bereich deklarieren. Da das zweite Skript nicht geladen wurde, ist diegreeting()Funktion aussecond.jsnicht verfügbar, um aufgerufen zu werden. -
Wenn wir die Zeile
const name = "Zaptec";aussecond.jsentfernen und die Seite neu laden würden, würden beide Skripte ausgeführt. Das Alert-Fenster würde jetztOur company is called Chris.anzeigen. Wenn eine Funktion neu deklariert wird, wird die letzte Deklaration in der Quellreihenfolge verwendet. Die vorherigen Deklarationen werden effektiv überschrieben.
Das Einschließen von Teilen Ihres Codes in Funktionen vermeidet solche Probleme und wird als Best Practice betrachtet.
Es ist ein bisschen wie ein Zoo. Die Löwen, Zebras, Tiger und Pinguine sind in ihren eigenen Gehegen untergebracht und haben nur Zugang zu den Dingen im Innern, ähnlich wie Funktionsbereiche. Wenn sie Zugang zu anderen Gehegen hätten, würden Probleme auftreten. Im besten Fall würden sich verschiedene Tierarten in unbekannten Lebensräumen sehr unwohl fühlen — ein Löwe oder Tiger würde sich furchtbar im wässrigen, eisigen Bereich der Pinguine fühlen. Im schlimmsten Fall könnten die Löwen und Tiger versuchen, die Pinguine zu fressen!

Der Zookeeper ist wie der globale Bereich — er hat die Schlüssel, um auf jedes Gehege zuzugreifen, Futter aufzufüllen, sich um kranke Tiere zu kümmern usw.
Mit dem Geltungsbereich spielen
Schauen wir uns ein reales Beispiel an, um den Geltungsbereich zu demonstrieren.
-
Machen Sie zuerst eine lokale Kopie unseres function-scope.html Beispiels. Es enthält zwei Funktionen, die
a()undb()genannt werden, und drei Variablen —x,yundz— zwei davon sind innerhalb der Funktionen definiert, und eine im globalen Bereich. Es enthält auch eine dritte Funktion, dieoutput()genannt wird, die ein einzelnes Argument nimmt und es in einem Absatz auf der Seite ausgibt. -
Öffnen Sie das Beispiel in einem Browser und in Ihrem Texteditor.
-
Öffnen Sie die JavaScript-Konsole in Ihrem Browser-Entwicklerwerkzeug. Geben Sie in der JavaScript-Konsole den folgenden Befehl ein:
jsoutput(x);Sie sollten den Wert der Variablen
xim Browser-Viewport angezeigt sehen. -
Versuchen Sie nun, Folgendes in Ihrer Konsole einzugeben:
jsoutput(y); output(z);Beide sollten einen Fehler in die Konsole werfen, der in etwa lautet "ReferenceError: y is not defined". Warum ist das so? Aufgrund des Funktionsbereichs:
yundzsind innerhalb dera()undb()Funktionen eingeschlossen, sodassoutput()sie nicht aufrufen kann, wenn es vom globalen Bereich aus aufgerufen wird. -
Wie aber, wenn es innerhalb einer anderen Funktion aufgerufen wird? Versuchen Sie,
a()undb()so zu bearbeiten, dass sie wie folgt aussehen:jsfunction a() { const y = 2; output(y); } function b() { const z = 3; output(z); }Speichern Sie den Code und laden Sie ihn in Ihrem Browser neu, und versuchen Sie dann, die
a()- undb()-Funktionen aus der JavaScript-Konsole aufzurufen:jsa(); b();Sie sollten die
y- undz-Werte im Browser-Viewport ausgedruckt sehen. Dies funktioniert einwandfrei, da dieoutput()-Funktion innerhalb der anderen Funktionen aufgerufen wird, im selben Bereich wie die Variablen, die sie ausgeben, definiert sind.output()selbst ist überall verfügbar, da es im globalen Bereich definiert ist. -
Versuchen Sie nun, Ihren Code wie folgt zu aktualisieren:
jsfunction a() { const y = 2; output(x); } function b() { const z = 3; output(x); } -
Speichern und laden Sie erneut, und versuchen Sie dies erneut in Ihrer JavaScript-Konsole:
jsa(); b();Beide Aufrufe von
a()undb()sollten den Wert von x im Browser-Viewport ausdrucken. Dies funktioniert einwandfrei, da trotz der Tatsache, dass dieoutput()-Aufrufe nicht im selben Bereich wiexdefiniert sind,xeine globale Variable ist — es ist in jedem Code überall zugänglich. -
Versuchen Sie schließlich, Ihren Code so zu aktualisieren:
jsfunction a() { const y = 2; output(z); } function b() { const z = 3; output(y); } -
Speichern und laden Sie erneut, und versuchen Sie dies erneut in Ihrer JavaScript-Konsole:
jsa(); b();Dieses Mal werden die Aufrufe von
a()undb()diesen lästigen ReferenceError: Variablenname is not defined Fehler in die Konsole werfen — das liegt daran, dass dieoutput()-Aufrufe und die Variablen, die sie ausdrucken sollen, nicht in denselben Funktionsbereichen sind — die Variablen sind effektiv für diese Funktionsaufrufe unsichtbar.
Hinweis: Der ReferenceError: "x" is not defined Fehler ist einer der häufigsten, auf den Sie stoßen werden. Wenn Sie diesen Fehler erhalten und sicher sind, dass Sie die betreffende Variable definiert haben, überprüfen Sie, in welchem Bereich sie sich befindet.
Eine Randbemerkung zu Schleifen- und Bedingungsbereichen
Es ist erwähnenswert, dass der Bereich von Werten, die innerhalb von Bedingungen und Schleifen deklariert sind, genauso funktioniert wie der Funktionsbereich, wenn Werte mit let und const deklariert werden. Zum Beispiel, wenn Sie die folgenden Blöcke zum obigen Beispiel hinzufügen würden:
if (x === 1) {
const c = 4;
let d = 5;
}
for (let i = 0; i <= 1; i++) {
const e = 6;
let f = 7;
}
Das Aufrufen von output(c), output(d), output(e) oder output(f) würde zu demselben "ReferenceError: [variablen-name] is not defined" Fehler führen, den wir vorher gesehen haben. Die output()-Funktion kann nicht auf diese Variablen zugreifen, weil sie in ihrem eigenen Bereich eingeschlossen sind.
Das veraltete var-Schlüsselwort funktioniert anders. Wenn c, d, e und f mit var deklariert wurden:
if (x === 1) {
var c = 4;
var d = 5;
}
for (let i = 0; i <= 1; i++) {
var e = 6;
var f = 7;
}
Würden sie in den globalen Bereich gehoben werden; daher würde das Ausgeben von ihnen in die Konsole (zum Beispiel mit output(c)) funktionieren. Variablen, die mit var innerhalb von Funktionen deklariert sind, haben jedoch immer noch ihren Bereich auf diese Funktionen beschränkt.
Diese Inkonsistenz kann Verwirrung und Fehler verursachen und ist ein weiterer Grund, warum let und const anstelle von var verwendet werden sollten.
Zusammenfassung
Dieser Artikel hat die grundlegenden Konzepte hinter Funktionen untersucht und den Weg für den nächsten Artikel geebnet, in dem wir praktisch werden und Sie durch die Schritte führen, um Ihre eigene benutzerdefinierte Funktion zu erstellen.
Siehe auch
- Detaillierter Leitfaden zu Funktionen — behandelt einige erweiterte Funktionen, die hier nicht enthalten sind.
- Funktionsreferenz
- Funktionen verwenden, um weniger Code zu schreiben, Scrimba MDN-Lernpartner - Eine interaktive Lektion, die eine nützliche Einführung in Funktionen bietet.