Funktionen
Baseline
Weitgehend verfügbar
*
Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit Juli 2015 browserübergreifend verfügbar.
* Einige Teile dieser Funktion werden möglicherweise unterschiedlich gut unterstützt.
Allgemein ist eine Funktion ein „Unterprogramm“, das von Code außerhalb der Funktion (oder im Fall von Rekursion innerhalb der Funktion) aufgerufen werden kann. Wie das Programm selbst besteht eine Funktion aus einer Folge von Anweisungen, dem Funktionskörper. Werte können als Parameter an eine Funktion übergeben werden, und die Funktion gibt einen Wert zurück.
In JavaScript sind Funktionen First-Class-Objekte, da sie an andere Funktionen übergeben, von Funktionen zurückgegeben sowie Variablen und Eigenschaften zugewiesen werden können. Wie jedes andere Objekt können sie außerdem Eigenschaften und Methoden haben. Von anderen Objekten unterscheiden sie sich dadurch, dass Funktionen aufgerufen werden können.
Weitere Beispiele und Erläuterungen finden Sie im JavaScript-Leitfaden zu Funktionen.
Beschreibung
Funktionswerte sind normalerweise Instanzen von Function. Informationen zu Eigenschaften und Methoden von Function-Objekten finden Sie unter Function. Bei aufrufbaren Werten gibt typeof "function" statt "object" zurück.
Hinweis:
Nicht alle aufrufbaren Werte sind instanceof Function. Beispielsweise ist das Objekt Function.prototype aufrufbar, aber keine Instanz von Function. Sie können auch die Prototypenkette Ihrer Funktion manuell so ändern, dass sie nicht mehr von Function.prototype erbt. Solche Fälle sind jedoch äußerst selten.
Rückgabewert
Wenn die Ausführung einer Funktion nicht mit einer return-Anweisung endet oder wenn auf das Schlüsselwort return kein Ausdruck folgt, ist der Rückgabewert standardmäßig undefined. Mit der return-Anweisung können Sie einen beliebigen Wert aus der Funktion zurückgeben. Ein Funktionsaufruf kann nur einen Wert zurückgeben. Sie können jedoch die Rückgabe mehrerer Werte simulieren, indem Sie ein Objekt oder Array zurückgeben und das Ergebnis destrukturieren.
Hinweis:
Für Konstruktoren, die mit new aufgerufen werden, gelten andere Regeln zur Bestimmung ihres Rückgabewerts.
Argumente übergeben
Parameter und Argumente haben leicht unterschiedliche Bedeutungen, werden in den MDN Web Docs aber häufig synonym verwendet. Als kurze Orientierung:
function formatNumber(num) {
return num.toFixed(2);
}
formatNumber(2);
In diesem Beispiel heißt die Variable num Parameter der Funktion: Sie wird in der von Klammern umschlossenen Liste der Funktionsdefinition deklariert. Die Funktion erwartet für den Parameter num eine Zahl – in JavaScript lässt sich das allerdings nur durch Code zur Laufzeitvalidierung erzwingen. Beim Aufruf formatNumber(2) ist die Zahl 2 das Argument der Funktion: Sie ist der Wert, der beim Funktionsaufruf tatsächlich an die Funktion übergeben wird. Innerhalb des Funktionskörpers kann über den entsprechenden Parameternamen oder das Objekt arguments auf den Argumentwert zugegriffen werden.
Argumente werden immer als Wert übergeben und nie als Referenz übergeben. Das bedeutet: Wenn eine Funktion einem Parameter einen neuen Wert zuweist, ändert sich der Wert außerhalb der Funktion nicht. Genauer gesagt werden Objektargumente durch Teilen übergeben. Werden Eigenschaften des Objekts verändert, wirkt sich diese Änderung also auch außerhalb der Funktion aus. 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, über das auf die Funktion zugegriffen wird – nicht auf die gerade ausgeführte Funktion. Daher müssen Sie auch innerhalb des Funktionskörpers über ihren Namen auf den Funktionswert verweisen.
Funktionen definieren
Grundsätzlich gibt es in JavaScript vier Arten von Funktionen:
- Reguläre Funktion: Kann einen beliebigen Wert zurückgeben; wird nach dem Aufruf immer vollständig ausgeführt.
- Generatorfunktion: Gibt ein
Generator-Objekt zurück; kann mit dem Operatoryieldangehalten und fortgesetzt werden. - Asynchrone Funktion: Gibt ein
Promisezurück; kann mit dem Operatorawaitangehalten und fortgesetzt werden. - Asynchrone Generatorfunktion: Gibt ein
AsyncGenerator-Objekt zurück; sowohl der Operatorawaitals auch der Operatoryieldkönnen verwendet werden.
Für jede Art von Funktion gibt es mehrere Möglichkeiten der Definition:
- Deklaration
- Ausdruck
- Konstruktor
-
Function(),GeneratorFunction(),AsyncFunction(),AsyncGeneratorFunction()
Darüber hinaus gibt es spezielle Syntax für die Definition von Pfeilfunktionen und Methoden, die eine genauere Semantik für deren Verwendung bietet. Klassen sind konzeptionell keine Funktionen (weil ihr Aufruf ohne new einen Fehler auslöst). Sie erben jedoch ebenfalls von Function.prototype, und für sie gilt 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 Syntaxvarianten bewirken ungefähr dasselbe, weisen aber einige feine Unterschiede im Verhalten auf.
- Der Konstruktor
Function()sowiefunction-Ausdrücke undfunction-Deklarationen erzeugen vollwertige Funktionsobjekte, die mitnewals Konstruktor aufgerufen werden können. Pfeilfunktionen und Methoden können dagegen nicht als Konstruktor aufgerufen werden. Asynchrone Funktionen, Generatorfunktionen und asynchrone Generatorfunktionen sind unabhängig von der Syntax nicht als Konstruktor aufrufbar. - Die
function-Deklaration erzeugt Funktionen, die durch Hoisting vorgezogen werden. Bei den anderen Syntaxvarianten findet kein Hoisting der Funktion statt; der Funktionswert ist erst nach seiner Definition verfügbar. - Pfeilfunktionen und der Konstruktor
Function()erzeugen immer anonyme Funktionen, die sich nicht ohne Weiteres rekursiv selbst aufrufen können. Eine Möglichkeit, eine Pfeilfunktion rekursiv aufzurufen, besteht darin, sie einer Variablen zuzuweisen. - Die Syntax für Pfeilfunktionen erzeugt keine eigenen Bindungen für
argumentsoderthis. - Der Konstruktor
Function()kann auf keine lokalen Variablen zugreifen – er hat nur Zugriff auf den globalen Gültigkeitsbereich. - Der Konstruktor
Function()bewirkt eine Kompilierung zur Laufzeit und ist häufig langsamer als andere Syntaxvarianten.
Bei function-Ausdrücken besteht ein Unterschied zwischen dem Funktionsnamen und der Variablen, der die Funktion zugewiesen wird. Der Funktionsname kann nicht geändert werden; der Variablen kann dagegen ein neuer Wert zugewiesen werden. Der Funktionsname kann sich vom Namen der Variablen unterscheiden, der die Funktion zugewiesen wird – zwischen beiden besteht keine Beziehung. Der Funktionsname kann nur innerhalb des Funktionskörpers verwendet werden. Ein Versuch, ihn außerhalb des Funktionskörpers zu verwenden, führt zu einem Fehler (oder liefert einen anderen Wert, falls derselbe Name an anderer Stelle deklariert wurde). Zum Beispiel:
const y = function x() {};
console.log(x); // ReferenceError: x is not defined
Für die Variable, der die Funktion zugewiesen wird, gilt dagegen nur die Einschränkung ihres Gültigkeitsbereichs. Dieser umfasst garantiert den Gültigkeitsbereich, in dem die Funktion deklariert wird.
Eine Funktionsdeklaration erzeugt außerdem eine Variable mit demselben Namen wie die Funktion. Anders als bei Funktionen, die durch Funktionsausdrücke definiert werden, kann auf Funktionen aus Funktionsdeklarationen daher sowohl in ihrem eigenen Funktionskörper als auch über ihren Namen in dem Gültigkeitsbereich zugegriffen werden, in dem sie definiert wurden.
Bei einer mit new Function definierten Funktion wird der Quelltext dynamisch zusammengesetzt. Das ist bei der Serialisierung der Funktion sichtbar. Beispielsweise ergibt console.log(new Function().toString()):
function anonymous(
) {
}
Dies ist der tatsächliche Quelltext, der zum Kompilieren der Funktion verwendet wird. Obwohl der Konstruktor Function() eine Funktion mit dem Namen anonymous erzeugt, wird dieser Name nicht zum Gültigkeitsbereich des Funktionskörpers hinzugefügt. Der Funktionskörper hat nur Zugriff auf globale Variablen. Das Folgende würde beispielsweise zu einem Fehler führen:
new Function("alert(anonymous);")();
Eine durch einen Funktionsausdruck oder eine Funktionsdeklaration definierte Funktion übernimmt den aktuellen Gültigkeitsbereich. Die Funktion bildet also eine Closure. Eine durch den Konstruktor Function definierte Funktion übernimmt dagegen außer dem globalen Gültigkeitsbereich (den alle Funktionen übernehmen) keinen weiteren Gültigkeitsbereich.
// 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 aus Funktionsausdrücken und Funktionsdeklarationen werden nur einmal geparst. Bei einer durch den Konstruktor Function definierten Funktion wird die übergebene Zeichenfolge hingegen bei jedem Aufruf des Konstruktors erneut geparst. Obwohl ein Funktionsausdruck jedes Mal eine Closure erzeugt, wird der Funktionskörper nicht erneut geparst. Funktionsausdrücke sind daher immer noch schneller als new Function(...). Deshalb sollte der Konstruktor Function nach Möglichkeit generell vermieden werden.
Eine Funktionsdeklaration kann unbeabsichtigt zu einem Funktionsausdruck werden, wenn sie in einem Ausdruckskontext steht.
// A function declaration
function foo() {
console.log("FOO!");
}
doSomething(
// A function expression passed as an argument
function foo() {
console.log("FOO!");
},
);
Umgekehrt kann auch ein Funktionsausdruck zu einer Funktionsdeklaration werden. Eine Ausdrucksanweisung darf nicht mit den Schlüsselwörtern function oder async function beginnen. Das ist ein häufiger Fehler bei der Implementierung von IIFEs (sofort aufgerufenen Funktionsausdrücken).
function () { // SyntaxError: Function statements require a function name
console.log("FOO!");
}();
function foo() {
console.log("FOO!");
}(); // SyntaxError: Unexpected token ')'
Beginnen Sie die Ausdrucksanweisung stattdessen mit etwas anderem, sodass das Schlüsselwort function eindeutig einen Funktionsausdruck einleitet. Übliche Möglichkeiten sind die 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 ermöglichen es, formale Parameter mit Standardwerten zu initialisieren, wenn kein Wert oder
undefinedübergeben wird. - Der Rest-Parameter ermöglicht es, eine unbestimmte Anzahl von Argumenten als Array darzustellen.
- Durch Destrukturierung lassen sich Elemente aus Arrays oder Eigenschaften aus Objekten in einzelne Variablen entpacken.
function myFunc({ a, b }, c = 1, ...rest) {
// You can access the values of a, b, c, and rest here
}
Die Verwendung einer der oben genannten nicht einfachen Parametersyntaxen hat einige Folgen:
- Sie können
"use strict"nicht im Funktionskörper verwenden – dies führt zu einem Syntaxfehler. - Auch wenn sich die Funktion nicht im Strict Mode befindet, gelten bestimmte Regeln des Strict Mode für Funktionen: Das Objekt
argumentswird nicht mehr mit den benannten Parametern synchronisiert, der Zugriff aufarguments.calleelöst einen Fehler aus, und doppelte Parameternamen sind nicht zulässig.
Das arguments-Objekt
Innerhalb einer Funktion können Sie über das Objekt arguments auf ihre Argumente zugreifen.
arguments-
Ein arrayähnliches Objekt, das die an die gerade ausgeführte Funktion übergebenen Argumente enthält.
arguments.callee-
Die gerade ausgeführte Funktion.
arguments.length-
Die Anzahl der an die Funktion übergebenen Argumente.
Getter- und Setter-Funktionen
Sie können Zugriffseigenschaften für jedes standardmäßig integrierte oder benutzerdefinierte Objekt definieren, das das Hinzufügen neuer Eigenschaften unterstützt. Innerhalb von Objektliteralen und Klassen können Sie spezielle Syntax verwenden, um Getter und Setter einer Zugriffseigenschaft zu definieren.
- get
-
Verknüpft eine Objekteigenschaft mit einer Funktion, die aufgerufen wird, wenn die Eigenschaft abgefragt wird.
- set
-
Verknüpft eine Objekteigenschaft mit einer Funktion, die aufgerufen wird, wenn versucht wird, die Eigenschaft zu setzen.
Beachten Sie, dass diese Syntaxvarianten eine Objekteigenschaft und keine Methode erzeugen. Auf die Getter- und Setter-Funktionen selbst kann nur über reflektierende APIs wie Object.getOwnPropertyDescriptor() zugegriffen werden.
Funktionen auf Blockebene
Im Strict Mode ist der Gültigkeitsbereich von Funktionen innerhalb eines Blocks auf diesen Block beschränkt. Vor ES2015 waren Funktionen auf Blockebene im Strict Mode nicht zulässig.
"use strict";
function f() {
return 1;
}
{
function f() {
return 2;
}
}
f() === 1; // true
// f() === 2 in non-strict mode
Funktionen auf Blockebene außerhalb des Strict Mode
Kurz gesagt: Tun Sie es nicht.
Außerhalb des Strict Mode verhalten sich Funktionsdeklarationen innerhalb von Blöcken ungewöhnlich. Zum Beispiel:
if (shouldDefineZero) {
function zero() {
// DANGER: compatibility risk
console.log("This is zero.");
}
}
Im Strict Mode ist die Semantik hierfür genau festgelegt: zero existiert nur innerhalb des Gültigkeitsbereichs des if-Blocks. Wenn shouldDefineZero falsch ist, sollte zero niemals definiert werden, da der Block nie ausgeführt wird. Historisch war dieses Verhalten jedoch nicht festgelegt, sodass verschiedene Browser es außerhalb des Strict Mode unterschiedlich implementierten. Weitere Informationen finden Sie in der Referenz zur function-Deklaration.
Eine sicherere Möglichkeit, Funktionen bedingt zu definieren, besteht darin, einer Variablen einen Funktionsausdruck 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
>Eine formatierte Zahl zurückgeben
Die folgende Funktion gibt eine Zeichenfolge zurück, die eine mit führenden Nullen aufgefüllte Zahl in formatierter Darstellung 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 Funktion padZeros auf.
let result;
result = padZeros(42, 4); // returns "0042"
result = padZeros(42, 2); // returns "42"
result = padZeros(5, 4); // returns "0005"
Prüfen, ob eine Funktion existiert
Mit dem Operator typeof können Sie feststellen, ob eine Funktion existiert. Im folgenden Beispiel wird geprüft, ob das Objekt window eine Eigenschaft namens noFunc besitzt, 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 bei der if-Prüfung eine Referenz auf noFunc verwendet wird: Auf den Funktionsnamen folgen keine Klammern (), sodass die Funktion selbst nicht aufgerufen wird.
Spezifikationen
| Spezifikation |
|---|
| ECMAScript® 2027 Language Specification> # sec-function-definitions> |