In JavaScript ist eine Funktion keine „magische Sprachstruktur“, sondern eine besondere Art von Wert.

Die Syntax, die wir zuvor verwendet haben, wird Funktionsdeklaration genannt:

function sayHi() { alert( "Hello" );}

Es gibt eine andere Syntax zum Erstellen einer Funktion, die Funktionsausdruck genannt wird.

Sie sieht so aus:

let sayHi = function() { alert( "Hello" );};

Hier wird die Funktion explizit erstellt und der Variablen zugewiesen, wie jeder andere Wert. Egal wie die Funktion definiert ist, sie ist einfach ein Wert, der in der Variablen sayHi gespeichert wird.

Die Bedeutung dieser Codebeispiele ist die gleiche: „Erstelle eine Funktion und lege sie in die Variable sayHi„.

Wir können diesen Wert sogar ausdrucken, indem wir alert verwenden:

function sayHi() { alert( "Hello" );}alert( sayHi ); // shows the function code

Bitte beachten Sie, dass die letzte Zeile die Funktion nicht ausführt, weil nach sayHi keine Klammern stehen. Es gibt Programmiersprachen, bei denen jede Erwähnung eines Funktionsnamens zu dessen Ausführung führt, aber bei JavaScript ist das nicht der Fall.

In JavaScript ist eine Funktion ein Wert, also können wir sie wie einen Wert behandeln. Der obige Code zeigt seine String-Repräsentation, die der Quellcode ist.

Sicherlich ist eine Funktion ein spezieller Wert, in dem Sinne, dass wir sie wie sayHi() aufrufen können.

Aber es ist immer noch ein Wert. Also können wir mit ihr arbeiten wie mit anderen Arten von Werten.

Wir können eine Funktion in eine andere Variable kopieren:

function sayHi() { // (1) create alert( "Hello" );}let func = sayHi; // (2) copyfunc(); // Hello // (3) run the copy (it works)!sayHi(); // Hello // this still works too (why wouldn't it)

Hier ist, was oben im Detail passiert:

  1. Die Funktionsdeklaration (1) erstellt die Funktion und setzt sie in die Variable namens sayHi.
  2. Zeile (2) kopiert sie in die Variable func. Bitte beachten Sie noch einmal: Nach sayHi stehen keine Klammern. Wäre das der Fall, dann würde func = sayHi() das Ergebnis des Aufrufs sayHi() in func schreiben, nicht die Funktion sayHi selbst.
  3. Jetzt kann die Funktion sowohl als sayHi() als auch als func() aufgerufen werden.

Beachten Sie, dass wir auch einen Funktionsausdruck hätten verwenden können, um sayHi in der ersten Zeile zu deklarieren:

let sayHi = function() { alert( "Hello" );};let func = sayHi;// ...

Alles würde genauso funktionieren.

Warum steht ein Semikolon am Ende?

Sie fragen sich vielleicht, warum der Funktionsausdruck ein Semikolon ; am Ende hat, die Funktionsdeklaration aber nicht:

function sayHi() { // ...}let sayHi = function() { // ...};

Die Antwort ist einfach:

  • Es besteht keine Notwendigkeit für ; am Ende von Codeblöcken und Syntaxstrukturen, die sie verwenden, wie if { ... }, for { }, function f { } usw.
  • Ein Funktionsausdruck wird innerhalb der Anweisung verwendet: let sayHi = ...;, als ein Wert. Es handelt sich nicht um einen Codeblock, sondern um eine Zuweisung. Das Semikolon ; wird am Ende von Anweisungen empfohlen, unabhängig davon, welchen Wert sie haben. Das Semikolon bezieht sich hier also nicht auf den Funktionsausdruck selbst, es beendet nur die Anweisung.

Rückruffunktionen

Schauen wir uns weitere Beispiele für die Übergabe von Funktionen als Werte und die Verwendung von Funktionsausdrücken an.

Wir schreiben eine Funktion ask(question, yes, no) mit drei Parametern:

questionText der Frage yesFunktion, die ausgeführt werden soll, wenn die Antwort „Ja“ lautet noFunktion, die ausgeführt werden soll, wenn die Antwort „Nein“ lautet

Die Funktion soll die question abfragen und, je nach Antwort des Benutzers, yes() oder no() aufrufen:

function ask(question, yes, no) { if (confirm(question)) yes() else no();}function showOk() { alert( "You agreed." );}function showCancel() { alert( "You canceled the execution." );}// usage: functions showOk, showCancel are passed as arguments to askask("Do you agree?", showOk, showCancel);

In der Praxis sind solche Funktionen recht nützlich. Der Hauptunterschied zwischen einer realen ask und dem obigen Beispiel besteht darin, dass reale Funktionen komplexere Möglichkeiten zur Interaktion mit dem Benutzer nutzen als eine einfache confirm. Im Browser zeichnet eine solche Funktion normalerweise ein hübsches Fragefenster. Aber das ist eine andere Geschichte.

Die Argumente showOk und showCancel von ask werden Callback-Funktionen oder einfach Callbacks genannt.

Die Idee ist, dass wir eine Funktion übergeben und erwarten, dass sie später „zurückgerufen“ wird, falls nötig. In unserem Fall wird showOk zum Rückruf für die Antwort „Ja“ und showCancel für die Antwort „Nein“.

Wir können Funktionsausdrücke verwenden, um die gleiche Funktion viel kürzer zu schreiben:

function ask(question, yes, no) { if (confirm(question)) yes() else no();}ask( "Do you agree?", function() { alert("You agreed."); }, function() { alert("You canceled the execution."); });

Hier werden Funktionen direkt innerhalb des ask(...)-Aufrufs deklariert. Sie haben keinen Namen und werden daher anonym genannt. Solche Funktionen sind außerhalb von ask nicht zugänglich (weil sie keinen Variablen zugewiesen sind), aber das ist genau das, was wir hier wollen.

Solcher Code taucht in unseren Skripten ganz natürlich auf, er entspricht dem Geist von JavaScript.

Eine Funktion ist ein Wert, der eine „Aktion“ repräsentiert.

Reguläre Werte wie Strings oder Zahlen repräsentieren die Daten.

Eine Funktion kann als eine Aktion wahrgenommen werden.

Wir können sie zwischen Variablen übergeben und ausführen, wann wir wollen.

Funktionsausdruck vs. Funktionsdeklaration

Lassen Sie uns die Hauptunterschiede zwischen Funktionsdeklarationen und Ausdrücken formulieren.

Erstens, die Syntax: wie man sie im Code unterscheidet.

  • Funktionsdeklaration: eine Funktion, die als separate Anweisung im Hauptcodefluss deklariert wird.

    // Function Declarationfunction sum(a, b) { return a + b;}

  • Funktionsausdruck: eine Funktion, die innerhalb eines Ausdrucks oder eines anderen Syntaxkonstrukts erstellt wird. Hier wird die Funktion auf der rechten Seite des „Zuweisungsausdrucks“ =:

    // Function Expressionlet sum = function(a, b) { return a + b;};

Der feinere Unterschied besteht darin, dass eine Funktion von der JavaScript-Engine erstellt wird.

Ein Funktionsausdruck wird erstellt, wenn die Ausführung ihn erreicht, und ist erst ab diesem Zeitpunkt verwendbar.

Sobald der Ausführungsfluss die rechte Seite der Zuweisung let sum = function… erreicht, ist die Funktion erstellt und kann von nun an verwendet werden (zugewiesen, aufgerufen, etc.).

Funktionsdeklarationen sind anders.

Eine Funktionsdeklaration kann früher aufgerufen werden, als sie definiert ist.

Eine globale Funktionsdeklaration ist zum Beispiel im ganzen Skript sichtbar, egal wo sie sich befindet.

Das liegt an internen Algorithmen. Wenn JavaScript die Ausführung des Skripts vorbereitet, sucht es zuerst nach globalen Funktionsdeklarationen darin und erstellt die Funktionen. Man kann sich das als eine „Initialisierungsphase“ vorstellen.

Und nachdem alle Funktionsdeklarationen verarbeitet wurden, wird der Code ausgeführt. Er hat also Zugriff auf diese Funktionen.

Das funktioniert zum Beispiel so:

sayHi("John"); // Hello, Johnfunction sayHi(name) { alert( `Hello, ${name}` );}

Die Funktionsdeklaration sayHi wird erstellt, wenn JavaScript den Start des Skripts vorbereitet und ist überall im Skript sichtbar.

…Wäre es ein Funktionsausdruck, dann würde es nicht funktionieren:

sayHi("John"); // error!let sayHi = function(name) { // (*) no magic any more alert( `Hello, ${name}` );};

Funktionsausdrücke werden erstellt, wenn die Ausführung sie erreicht. Das würde nur in der Zeile (*) passieren. Zu spät.

Eine weitere Besonderheit von Funktionsdeklarationen ist ihr Blockumfang.

Im Strict-Modus ist eine Funktionsdeklaration, die sich innerhalb eines Codeblocks befindet, überall innerhalb dieses Blocks sichtbar. Aber nicht außerhalb des Blocks.

Angenommen, wir müssen eine Funktion welcome() deklarieren, die von der Variable age abhängt, die wir während der Laufzeit erhalten. Wenn wir die Funktionsdeklaration verwenden, wird sie nicht wie vorgesehen funktionieren:

let age = prompt("What is your age?", 18);// conditionally declare a functionif (age < 18) { function welcome() { alert("Hello!"); }} else { function welcome() { alert("Greetings!"); }}// ...use it laterwelcome(); // Error: welcome is not defined

Das liegt daran, dass eine Funktionsdeklaration nur innerhalb des Codeblocks sichtbar ist, in dem sie sich befindet.

Hier ein weiteres Beispiel:

let age = 16; // take 16 as an exampleif (age < 18) { welcome(); // \ (runs) // | function welcome() { // | alert("Hello!"); // | Function Declaration is available } // | everywhere in the block where it's declared // | welcome(); // / (runs)} else { function welcome() { alert("Greetings!"); }}// Here we're out of curly braces,// so we can not see Function Declarations made inside of them.welcome(); // Error: welcome is not defined

Was können wir tun, um welcome außerhalb von if sichtbar zu machen?

Der richtige Ansatz wäre, einen Funktionsausdruck zu verwenden und welcome der Variablen zuzuweisen, die außerhalb von if deklariert ist und die richtige Sichtbarkeit hat.

Dieser Code funktioniert wie vorgesehen:

let age = prompt("What is your age?", 18);let welcome;if (age < 18) { welcome = function() { alert("Hello!"); };} else { welcome = function() { alert("Greetings!"); };}welcome(); // ok now

Oder wir könnten ihn noch weiter vereinfachen, indem wir einen Fragezeichenoperator ? verwenden:

let age = prompt("What is your age?", 18);let welcome = (age < 18) ? function() { alert("Hello!"); } : function() { alert("Greetings!"); };welcome(); // ok now

Wann wählt man Funktionsdeklaration versus Funktionsausdruck?

Als Faustregel gilt: Wenn wir eine Funktion deklarieren müssen, sollten wir zuerst die Syntax der Funktionsdeklaration wählen. Sie gibt uns mehr Freiheit bei der Organisation unseres Codes, da wir solche Funktionen aufrufen können, bevor sie deklariert werden.

Das ist auch besser für die Lesbarkeit, da es einfacher ist, function f(…) {…} im Code nachzuschlagen als let f = function(…) {…};. Funktionsdeklarationen sind „auffälliger“.

…Aber wenn eine Funktionsdeklaration aus irgendeinem Grund nicht passt oder wir eine bedingte Deklaration brauchen (wir haben gerade ein Beispiel gesehen), dann sollte ein Funktionsausdruck verwendet werden.

Zusammenfassung

  • Funktionen sind Werte. Sie können an jeder beliebigen Stelle des Codes zugewiesen, kopiert oder deklariert werden.
  • Wenn die Funktion als separate Anweisung im Hauptcodefluss deklariert wird, nennt man das eine „Funktionsdeklaration“.
  • Wenn die Funktion als Teil eines Ausdrucks erstellt wird, nennt man das einen „Funktionsausdruck“.
  • Funktionsdeklarationen werden verarbeitet, bevor der Codeblock ausgeführt wird. Sie sind überall im Block sichtbar.
  • Funktionsausdrücke werden erstellt, wenn der Ausführungsfluss sie erreicht.

In den meisten Fällen, in denen wir eine Funktion deklarieren müssen, ist eine Funktionsdeklaration vorzuziehen, da sie vor der eigentlichen Deklaration sichtbar ist. Das gibt uns mehr Flexibilität bei der Codeorganisation und ist in der Regel besser lesbar.

Wir sollten also einen Funktionsausdruck nur dann verwenden, wenn eine Funktionsdeklaration für die Aufgabe nicht geeignet ist. Wir haben in diesem Kapitel ein paar Beispiele dafür gesehen und werden in Zukunft noch mehr sehen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.