Funktionen
Baseline Widely available *
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
* Some parts of this feature may have varying levels of support.
Im Allgemeinen ist eine Funktion ein "Unterprogramm", das von Code außerhalb (oder innerhalb, im Fall von Rekursion) der Funktion aufgerufen werden kann. Wie das Programm selbst besteht eine Funktion aus einer Abfolge von Anweisungen, die als Funktionskörper bezeichnet werden. Werte können als Parameter an eine Funktion übergeben werden, und die Funktion wird einen Wert zurückgeben.
In JavaScript sind Funktionen Objekte erster Klasse, da sie an andere Funktionen übergeben, von Funktionen zurückgegeben und Variablen und Eigenschaften zugewiesen werden können. Sie können auch Eigenschaften und Methoden wie jedes andere Objekt haben. Was sie von anderen Objekten unterscheidet, ist, dass Funktionen aufgerufen werden können.
Für weitere Beispiele und Erklärungen siehe den JavaScript-Leitfaden über Funktionen.
Beschreibung
Funktionswerte sind typischerweise Instanzen von Function
. Siehe Function
für Informationen zu Eigenschaften und Methoden von Function
-Objekten. Aufrufbare Werte bewirken, dass typeof
den Wert "function"
anstelle von "object"
ausgibt.
Hinweis:
Nicht alle aufrufbaren Werte sind instanceof Function
. Zum Beispiel ist das Function.prototype
-Objekt aufrufbar, aber keine Instanz von Function
. Sie können auch manuell die Prototypenkette Ihrer Funktion setzen, sodass sie nicht mehr von Function.prototype
erbt. Solche Fälle sind jedoch extrem selten.
Rückgabewert
Standardmäßig, wenn die Ausführung einer Funktion nicht mit einer return
-Anweisung endet oder wenn das return
-Schlüsselwort keinen Ausdruck danach hat, ist der Rückgabewert undefined
. Die return
-Anweisung ermöglicht es Ihnen, einen beliebigen Wert aus der Funktion zurückzugeben. Ein Funktionsaufruf kann nur einen Wert zurückgeben, aber Sie können den Effekt der Rückgabe mehrerer Werte simulieren, indem Sie ein Objekt oder Array zurückgeben und das Ergebnis destruieren.
Hinweis:
Konstruktoren, die mit new
aufgerufen werden, haben eine andere Logik zur Bestimmung ihrer Rückgabewerte.
Argumente übergeben
Parameter und Argumente haben leicht unterschiedliche Bedeutungen, aber in den MDN-Web-Dokumenten verwenden wir sie oft synonym. Für eine schnelle Referenz:
function formatNumber(num) {
return num.toFixed(2);
}
formatNumber(2);
In diesem Beispiel wird die Variable num
als Parameter der Funktion bezeichnet: Sie wird in der von Klammern umschlossenen Liste der Funktionsdefinition deklariert. Die Funktion erwartet, dass der num
-Parameter eine Zahl ist — obwohl dies in JavaScript nicht ohne Runtime-Validierungscode durchsetzbar ist. Im Aufruf formatNumber(2)
ist die Zahl 2
das Argument der Funktion: Es ist der Wert, der tatsächlich beim Funktionsaufruf an die Funktion übergeben wird. Der Argumentwert kann innerhalb des Funktionskörpers über den entsprechenden Parameternamen oder das arguments
-Objekt aufgerufen werden.
Argumente werden immer by value übergeben und nie by reference. Das bedeutet, dass, wenn eine Funktion einen Parameter neu zuordnet, sich der Wert außerhalb der Funktion nicht ändert. Genauer gesagt, Objektargumente werden by sharing übergeben, was bedeutet, dass, wenn die Eigenschaften des Objekts verändert werden, die Änderung Auswirkungen außerhalb der Funktion haben wird. Zum Beispiel:
function updateBrand(obj) {
// Mutating the object is visible outside the function
obj.brand = "Toyota";
// Try to reassign the parameter, but this won't affect
// the variable's value outside the function
obj = null;
}
const car = {
brand: "Honda",
model: "Accord",
year: 1998,
};
console.log(car.brand); // Honda
// Pass object reference to the function
updateBrand(car);
// updateBrand mutates car
console.log(car.brand); // Toyota
Das Schlüsselwort this
bezieht sich auf das Objekt, auf dem die Funktion aufgerufen wird — es bezieht sich nicht auf die aktuell ausgeführte Funktion, daher muss der Funktionswert auch innerhalb des Funktionskörpers namentlich referenziert werden.
Funktionen definieren
Allgemein gesagt, hat JavaScript vier Arten von Funktionen:
- Reguläre Funktion: kann alles zurückgeben; wird immer nach dem Aufruf vollständig ausgeführt
- Generatorfunktion: gibt ein
Generator
-Objekt zurück; kann mit demyield
-Operator pausiert und wieder aufgenommen werden - Asynchrone Funktion: gibt ein
Promise
zurück; kann mit demawait
-Operator pausiert und wieder aufgenommen werden - Asynchrone Generatorfunktion: gibt ein
AsyncGenerator
-Objekt zurück; sowohl dieawait
- als auchyield
-Operatoren können verwendet werden
Für jede Art von Funktion gibt es mehrere Möglichkeiten, sie zu definieren:
- Deklaration
- Ausdruck
- Konstruktor
-
Function()
,GeneratorFunction()
,AsyncFunction()
,AsyncGeneratorFunction()
Darüber hinaus gibt es spezielle Syntaxen zum Definieren von Pfeilfunktionen und Methoden, die genauere Semantiken für ihre Verwendung bieten. Klassen sind konzeptionell keine Funktionen (da sie einen Fehler werfen, wenn sie ohne new
aufgerufen werden), aber sie erben auch von Function.prototype
und haben typeof MyClass === "function"
.
// Constructor
const multiply = new Function("x", "y", "return x * y");
// Declaration
function multiply(x, y) {
return x * y;
} // No need for semicolon here
// Expression; the function is anonymous but assigned to a variable
const multiply = function (x, y) {
return x * y;
};
// Expression; the function has its own name
const multiply = function funcName(x, y) {
return x * y;
};
// Arrow function
const multiply = (x, y) => x * y;
// Method
const obj = {
multiply(x, y) {
return x * y;
},
};
Alle Syntaxen tun ungefähr dasselbe, aber es gibt einige subtile Verhaltensunterschiede.
- Die
Function()
-Konstruktor-,function
-Ausdrucks- undfunction
-Deklarations-Syntaxen erstellen vollwertige Funktionsobjekte, die mitnew
konstruiert werden können. Allerdings können Pfeilfunktionen und Methoden nicht konstruiert werden. Asynchrone Funktionen, Generatorfunktionen und asynchrone Generatorfunktionen sind unabhängig von der Syntax nicht konstruierbar. - Die
function
-Deklaration erstellt Funktionen, die gehoistet werden. Andere Syntaxen hoisten die Funktion nicht und der Funktionswert ist erst nach der Definition sichtbar. - Die Pfeilfunktions- und
Function()
-Konstruktor-Syntax erstellt immer anonyme Funktionen, was bedeutet, dass sie sich nicht leicht rekursiv aufrufen können. Eine Möglichkeit, eine Pfeilfunktion rekursiv aufzurufen, besteht darin, sie einer Variablen zuzuweisen. - Die Pfeilfunktions-Syntax hat keinen Zugriff auf
arguments
oderthis
. - Der
Function()
-Konstruktor kann auf keine lokalen Variablen zugreifen — er hat nur Zugriff auf den globalen Umfang. - Der
Function()
-Konstruktor verursacht eine Laufzeitkompilierung und ist oft langsamer als andere Syntaxen.
Bei function
-Ausdrücken gibt es einen Unterschied zwischen dem Funktionsnamen und der Variablen, der die Funktion zugewiesen ist. Der Funktionsname kann nicht geändert werden, während die Variable, der die Funktion zugewiesen ist, neu zugewiesen werden kann. Der Funktionsname kann vom Namen der Variablen, der die Funktion zugewiesen ist, abweichen — sie haben keine Beziehung zueinander. Der Funktionsname kann nur innerhalb des Funktionskörpers verwendet werden. Der Versuch, ihn außerhalb des Funktionskörpers zu verwenden, führt zu einem Fehler (oder erhält einen anderen Wert, wenn derselbe Name anderswo deklariert wurde). Zum Beispiel:
const y = function x() {};
console.log(x); // ReferenceError: x is not defined
Andererseits ist die Variable, der die Funktion zugewiesen ist, nur durch ihren Gültigkeitsbereich begrenzt, der garantiert den Gültigkeitsbereich einschließt, in dem die Funktion deklariert wurde.
Eine Funktionsdeklaration erstellt auch eine Variable mit demselben Namen wie der Funktionsname. Daher können Funktionen, die durch Funktionsdeklarationen definiert wurden, im Gültigkeitsbereich, in dem sie definiert wurden, sowie in ihrem eigenen Körper durch ihren Namen aufgerufen werden, im Gegensatz zu jenen, die durch Funktionsausdrücke definiert sind.
Eine Funktion, die durch new Function
definiert wurde, wird dynamisch mit ihrer Quelle zusammengebaut, was beobachtbar ist, wenn Sie sie serialisieren. Zum Beispiel gibt console.log(new Function().toString())
aus:
function anonymous(
) {
}
Dies ist die tatsächliche Quelle, die zum Kompilieren der Funktion verwendet wird. Allerdings wird, obwohl der Function()
-Konstruktor die Funktion mit dem Namen anonymous
erstellt, dieser Name nicht zum Gültigkeitsbereich des Körpers hinzugefügt. Der Körper hat nur jemals Zugriff auf globale Variablen. Zum Beispiel würde das Folgende zu einem Fehler führen:
new Function("alert(anonymous);")();
Eine Funktion, die durch einen Funktionsausdruck oder durch eine Funktionsdeklaration definiert wird, erbt den aktuellen Gültigkeitsbereich. Das heißt, die Funktion bildet einen Abschluss. Auf der anderen Seite erbt eine Funktion, die durch einen Function
-Konstruktor definiert wird, keinen Gültigkeitsbereich außer dem globalen Gültigkeitsbereich (den alle Funktionen erben).
// p is a global variable
globalThis.p = 5;
function myFunc() {
// p is a local variable
const p = 9;
function decl() {
console.log(p);
}
const expr = function () {
console.log(p);
};
const cons = new Function("\tconsole.log(p);");
decl();
expr();
cons();
}
myFunc();
// Logs:
// 9 (for 'decl' by function declaration (current scope))
// 9 (for 'expr' by function expression (current scope))
// 5 (for 'cons' by Function constructor (global scope))
Funktionen, die durch Funktionsausdrücke und Funktionsdeklarationen definiert werden, werden nur einmal geparst, während eine Funktion, die durch den Function
-Konstruktor definiert wird, den übergebenen String jedes Mal, wenn der Konstruktor aufgerufen wird, neu parst. Auch wenn ein Funktionsausdruck jedes Mal einen Abschluss erstellt, wird der Funktionskörper nicht neu geparst, sodass Funktionsausdrücke immer noch schneller sind als new Function(...)
. Daher sollte der Function
-Konstruktor nach Möglichkeit vermieden werden.
Eine Funktionsdeklaration kann unbeabsichtigt in einen Funktionsausdruck umgewandelt werden, wenn sie in einem Ausdruckskontext erscheint.
// A function declaration
function foo() {
console.log("FOO!");
}
doSomething(
// A function expression passed as an argument
function foo() {
console.log("FOO!");
},
);
Auf der anderen Seite kann ein Funktionsausdruck auch in eine Funktionsdeklaration umgewandelt werden. Eine Ausdrucksanweisung kann nicht mit den Schlüsselwörtern function
oder async function
beginnen, was ein häufiger Fehler beim Implementieren von IIFEs (Sofort Ausgeführte Funktionsausdrücke) ist.
function () { // SyntaxError: Function statements require a function name
console.log("FOO!");
}();
function foo() {
console.log("FOO!");
}(); // SyntaxError: Unexpected token ')'
Stattdessen sollten Sie die Ausdrucksanweisung mit etwas anderem beginnen, sodass das Schlüsselwort function
eindeutig einen Funktionsausdruck startet. Häufige Optionen sind Gruppierung und die Verwendung von void
.
(function () {
console.log("FOO!");
})();
void function () {
console.log("FOO!");
}();
Funktionsparameter
Jeder Funktionsparameter ist ein einfacher Bezeichner, auf den Sie im lokalen Gültigkeitsbereich zugreifen können.
function myFunc(a, b, c) {
// You can access the values of a, b, and c here
}
Es gibt drei spezielle Parametersyntaxen:
- Standardparameter erlauben es, formale Parameter mit Standardwerten zu initialisieren, wenn kein Wert oder
undefined
übergeben wird. - Der Restparameter erlaubt die Darstellung einer unbegrenzten Anzahl von Argumenten als Array.
- Destrukturierung ermöglicht das Aufteilen von Elementen aus Arrays oder Eigenschaften aus Objekten in separate Variablen.
function myFunc({ a, b }, c = 1, ...rest) {
// You can access the values of a, b, c, and rest here
}
Es gibt einige Konsequenzen, wenn eine der oben genannten nicht einfachen Parametersyntaxen verwendet wird:
- Sie können
"use strict"
nicht auf den Funktionskörper anwenden — dies führt zu einem Syntaxfehler. - Selbst wenn die Funktion nicht im Strict-Modus ist, gelten bestimmte Funktionen des Strict-Modus für Funktionen, einschließlich dass das
arguments
-Objekt nicht mehr mit den benannten Parametern synchronisiert wird,arguments.callee
beim Zugriff einen Fehler wirft und doppelte Parameternamen nicht erlaubt sind.
Das Arguments-Objekt
Sie können auf die Argumente einer Funktion innerhalb der Funktion durch das arguments
-Objekt zugreifen.
arguments
-
Ein array-ähnliches Objekt, das die an die derzeit ausgeführte Funktion übergebenen Argumente enthält.
arguments.callee
-
Die derzeit ausgeführte Funktion.
arguments.length
-
Die Anzahl der an die Funktion übergebenen Argumente.
Getter- und Setter-Funktionen
Sie können Zugriffsorperties auf jedem Standard- oder benutzerdefinierten Objekt definieren, das die Hinzufügung neuer Eigenschaften unterstützt. Innerhalb von Objektliteralen und Klassen können Sie spezielle Syntaxen verwenden, um den Getter und Setter einer Zugriffsproperty zu definieren.
- get
-
Verknüpft eine Objekteigenschaft mit einer Funktion, die aufgerufen wird, wenn auf diese Eigenschaft zugegriffen wird.
- set
-
Verknüpft eine Objekteigenschaft mit einer Funktion, die aufgerufen wird, wenn versucht wird, diese Eigenschaft festzulegen.
Beachten Sie, dass diese Syntaxen eine Objekteigenschaft erstellen, nicht eine Methode. Die Getter- und Setter-Funktionen selbst können nur mit reflektierenden APIs wie Object.getOwnPropertyDescriptor()
aufgerufen werden.
Block-Level Funktionen
Im Strict-Modus sind Funktionen innerhalb von Blöcken auf diesen Block beschränkt. Vor ES2015 waren Block-Level-Funktionen im Strict-Modus verboten.
"use strict";
function f() {
return 1;
}
{
function f() {
return 2;
}
}
f() === 1; // true
// f() === 2 in non-strict mode
Block-Level Funktionen in nicht-striktem Code
Kurz gesagt: Tun Sie es nicht.
In nicht-striktem Code verhalten sich Funktionsdeklarationen innerhalb von Blöcken merkwürdig. Zum Beispiel:
if (shouldDefineZero) {
function zero() {
// DANGER: compatibility risk
console.log("This is zero.");
}
}
Die Semantik davon im Strict-Modus ist gut spezifiziert — zero
existiert nur innerhalb des Geltungsbereichs des if
-Blocks. Wenn shouldDefineZero
false ist, sollte zero
nie definiert werden, da der Block nie ausgeführt wird. Historisch gesehen war dies jedoch nicht spezifiziert, sodass verschiedene Browser es in nicht-striktem Modus unterschiedlich implementierten. Weitere Informationen finden Sie im Verweis zur function
Deklaration.
Eine sicherere Methode zum bedingten Definieren von Funktionen besteht darin, einen Funktionsausdruck einer Variablen zuzuweisen:
// Using a var makes it available as a global variable,
// with closer behavior to a top-level function declaration
var zero;
if (shouldDefineZero) {
zero = function () {
console.log("This is zero.");
};
}
Beispiele
Zurückgeben einer formatierten Zahl
Die folgende Funktion gibt eine Zeichenkette zurück, die die formatierte Darstellung einer Zahl mit führenden Nullen enthält.
// This function returns a string padded with leading zeros
function padZeros(num, totalLen) {
let numStr = num.toString(); // Initialize return value as string
const numZeros = totalLen - numStr.length; // Calculate no. of zeros
for (let i = 1; i <= numZeros; i++) {
numStr = `0${numStr}`;
}
return numStr;
}
Die folgenden Anweisungen rufen die padZeros
-Funktion auf.
let result;
result = padZeros(42, 4); // returns "0042"
result = padZeros(42, 2); // returns "42"
result = padZeros(5, 4); // returns "0005"
Bestimmen, ob eine Funktion existiert
Sie können feststellen, ob eine Funktion existiert, indem Sie den typeof
-Operator verwenden. Im folgenden Beispiel wird ein Test durchgeführt, um zu ermitteln, ob das window
-Objekt eine Eigenschaft namens noFunc
hat, die eine Funktion ist. Wenn ja, wird sie verwendet; andernfalls wird eine andere Aktion ausgeführt.
if (typeof window.noFunc === "function") {
// use noFunc()
} else {
// do something else
}
Beachten Sie, dass im if
-Test ein Verweis auf noFunc
verwendet wird — es gibt keine Klammern ()
nach dem Funktionsnamen, sodass die eigentliche Funktion nicht aufgerufen wird.
Spezifikationen
Specification |
---|
ECMAScript® 2025 Language Specification # sec-function-definitions |