function expression
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.
Das function Schlüsselwort kann verwendet werden, um eine Funktion innerhalb eines Ausdrucks zu definieren.
Sie können auch Funktionen mit der function Deklaration oder der Pfeilsyntax definieren.
Probieren Sie es aus
const getRectArea = function (width, height) {
return width * height;
};
console.log(getRectArea(3, 4));
// Expected output: 12
Syntax
function (param0) {
statements
}
function (param0, param1) {
statements
}
function (param0, param1, /* …, */ paramN) {
statements
}
function name(param0) {
statements
}
function name(param0, param1) {
statements
}
function name(param0, param1, /* …, */ paramN) {
statements
}
Hinweis:
Eine Ausdrucksanweisung kann nicht mit dem Schlüsselwort function beginnen, um Verwechslungen mit einer function Deklaration zu vermeiden. Das function Schlüsselwort leitet nur dann einen Ausdruck ein, wenn es in einem Kontext erscheint, der keine Anweisungen akzeptieren kann.
Parameter
nameOptional-
Der Funktionsname. Kann weggelassen werden, in welchem Fall die Funktion anonym ist. Der Name ist nur lokal für den Funktionskörper.
paramNOptional-
Der Name eines formalen Parameters für die Funktion. Für die Syntax der Parameter, siehe die Funktionen-Referenz.
statementsOptional-
Die Anweisungen, die den Körper der Funktion ausmachen.
Beschreibung
Ein function Ausdruck ist dem function Deklaration sehr ähnlich und hat nahezu die gleiche Syntax. Der Hauptunterschied zwischen einem function Ausdruck und einer function Deklaration ist der Funktionsname, der bei function Ausdrücken weggelassen werden kann, um anonyme Funktionen zu erstellen. Ein function Ausdruck kann als IIFE (Sofort ausgeführter Funktionsausdruck) verwendet werden, der ausgeführt wird, sobald er definiert ist. Siehe auch das Kapitel über Funktionen für weitere Informationen.
Hoisting von Function Expressions
Function Expressions in JavaScript werden nicht "gehoben", anders als function declarations. Sie können Function Expressions nicht verwenden, bevor Sie sie erstellen:
console.log(notHoisted); // undefined
// Even though the variable name is hoisted,
// the definition isn't. so it's undefined.
notHoisted(); // TypeError: notHoisted is not a function
var notHoisted = function () {
console.log("bar");
};
Named Function Expression
Wenn Sie auf die aktuelle Funktion innerhalb des Funktionskörpers verweisen möchten, müssen Sie einen benannten Funktionsausdruck erstellen. Dieser Name ist dann nur lokal für den Funktionskörper (Scope). Dies vermeidet die Nutzung der veralteten arguments.callee Eigenschaft, um die Funktion rekursiv aufzurufen.
const math = {
factorial: function factorial(n) {
console.log(n);
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
},
};
math.factorial(3); // 3;2;1;
Wenn ein Funktionsausdruck benannt ist, wird die name Eigenschaft der Funktion auf diesen Namen gesetzt, anstelle des impliziten Namens, der aus der Syntax abgeleitet wird (wie die Variable, der die Funktion zugewiesen ist).
Im Gegensatz zu Deklarationen ist der Name der Function Expressions schreibgeschützt.
"use strict";
function foo() {
foo = 1;
}
foo();
console.log(foo); // 1
(function foo() {
foo = 1; // TypeError: Assignment to constant variable.
})();
Beispiele
>Verwendung von Function Expression
Das folgende Beispiel definiert eine unbenannte Funktion und weist sie x zu. Die Funktion gibt das Quadrat ihres Arguments zurück:
const x = function (y) {
return y * y;
};
Verwendung einer Funktion als Callback
Häufiger wird sie als Callback verwendet:
button.addEventListener("click", function (event) {
console.log("button is clicked!");
});
Verwendung eines Sofort Ausgeführten Funktionsausdrucks (IIFE)
IIFEs sind ein verbreitetes Muster, um beliebig viele Anweisungen in ihrem eigenen Scope auszuführen (und möglicherweise einen Wert zurückzugeben), an einem Ort, der einen einzelnen Ausdruck erfordert. Viele traditionelle Anwendungsfälle von IIFEs wurden durch neue Syntaxmerkmale wie Module und Block-skopierte Deklarationen überholt. IIFEs werden heutzutage häufiger mit Pfeilfunktionen geschrieben, aber die Idee bleibt die gleiche. Im Allgemeinen sehen IIFEs so aus:
// standard IIFE
(function () {
// statements…
})();
// IIFE with arguments
(function (a, b) {
console.log(a + b);
})(1, 2); // logs 3
// IIFE being used to initialize a variable
const value = (() => {
const randomValue = Math.random();
if (randomValue > 0.5) {
return "heads";
}
return "tails";
})();
Hier stellen wir mehrere Anwendungsfälle mit Beispielen vor.
Vermeidung der Verschmutzung des globalen Namensraums im Skriptcode
Der oberste Scope aller Skripte ist geteilt, was viele Funktionen und globale Variablen aus verschiedenen Dateien umfassen könnte. Um Namenskonflikte zu vermeiden, ist es wichtig, die Anzahl der global deklarierten Namen zu begrenzen (dies wird in Modulen stark gemindert, aber manchmal ist es trotzdem nützlich, den Scope temporärer Variablen zu begrenzen, insbesondere wenn die Datei sehr lang ist). Wenn wir Initialisierungscode haben, den wir nicht wieder verwenden müssen, könnten wir das IIFE-Muster benutzen, das besser ist als eine Funktionsdeklaration oder ein Funktionsausdruck, weil es sicherstellt, dass der Code nur hier und einmal ausgeführt wird.
// top-level of a script (not a module)
var globalVariable = (() => {
// some initialization code
let firstVariable = something();
let secondVariable = somethingElse();
return firstVariable + secondVariable;
})();
// firstVariable and secondVariable cannot be accessed outside of the function body.
Das Modulmuster
Wir würden auch IIFE verwenden, um private und öffentliche Variablen und Methoden zu erstellen. Für eine anspruchsvollere Nutzung des Modulmusters und andere Verwendungen von IIFE könnten Sie das Buch "Learning JavaScript Design Patterns" von Addy Osmani sehen.
const makeWithdraw = (balance) =>
((copyBalance) => {
let balance = copyBalance; // This variable is private
const doBadThings = () => {
console.log("I will do bad things with your money");
};
doBadThings();
return {
withdraw(amount) {
if (balance >= amount) {
balance -= amount;
return balance;
}
return "Insufficient money";
},
};
})(balance);
const firstAccount = makeWithdraw(100); // "I will do bad things with your money"
console.log(firstAccount.balance); // undefined
console.log(firstAccount.withdraw(20)); // 80
console.log(firstAccount.withdraw(30)); // 50
console.log(firstAccount.doBadThings); // undefined; this method is private
const secondAccount = makeWithdraw(20); // "I will do bad things with your money"
console.log(secondAccount.withdraw(30)); // "Insufficient money"
console.log(secondAccount.withdraw(20)); // 0
For-Schleife mit var vor ES6
Wir könnten die folgende Verwendung von IIFE in einigen alten Codes sehen, bevor die block-skopierten let und const Deklarationen eingeführt wurden. Mit der Anweisung var haben wir nur Funktions-Scope und den globalen Scope. Angenommen, wir wollen 2 Buttons mit den Texten Button 0 und Button 1 erstellen und wenn wir sie anklicken, sollen sie 0 und 1 anzeigen. Der folgende Code funktioniert nicht:
for (var i = 0; i < 2; i++) {
const button = document.createElement("button");
button.innerText = `Button ${i}`;
button.onclick = function () {
console.log(i);
};
document.body.appendChild(button);
}
console.log(i); // 2
Bei einem Klick zeigen sowohl Button 0 als auch Button 1 2 an, weil i global ist, mit dem letzten Wert 2. Um dieses Problem vor ES6 zu beheben, könnten wir das IIFE-Muster verwenden:
for (var i = 0; i < 2; i++) {
const button = document.createElement("button");
button.innerText = `Button ${i}`;
button.onclick = (function (copyOfI) {
return function () {
console.log(copyOfI);
};
})(i);
document.body.appendChild(button);
}
console.log(i); // 2
Bei einem Klick zeigen die Buttons 0 und 1 0 und 1 an. Die Variable i ist global definiert. Mit der Anweisung let könnten wir einfach tun:
for (let i = 0; i < 2; i++) {
const button = document.createElement("button");
button.innerText = `Button ${i}`;
button.onclick = function () {
console.log(i);
};
document.body.appendChild(button);
}
console.log(i); // Uncaught ReferenceError: i is not defined.
Bei einem Klick zeigen diese Buttons 0 und 1 an.
Kontrollflussanweisungen in Ausdruckspositionen
IIFEs ermöglichen es uns, Sprachkonstrukte wie switch in einem Ausdruck zu verwenden.
someObject.property = (() => {
switch (someVariable) {
case 0:
return "zero";
case 1:
return "one";
default:
return "unknown";
}
})();
Dieser Ansatz kann besonders nützlich sein in Szenarien, in denen Sie eine Variable const machen wollen, aber gezwungen sind, let oder var während der Initialisierung zu verwenden:
let onlyAssignedOnce;
try {
onlyAssignedOnce = someFunctionThatMightThrow();
} catch (e) {
onlyAssignedOnce = null;
}
Mit IIFEs können wir die Variable const machen:
const onlyAssignedOnce = (() => {
try {
return someFunctionThatMightThrow();
} catch (e) {
return null;
}
})();
Spezifikationen
| Spezifikation |
|---|
| ECMAScript® 2027 Language Specification> # sec-function-definitions> |
Browser-Kompatibilität
Siehe auch
- Funktionen Leitfaden
- Funktionen
functionFunction- Arrow functions