JavaScript-Currying und partielle Anwendung
Currying und partielle Anwendung sind leistungsstarke funktionale Programmiertechniken, die die Modularität und Wiederverwendbarkeit Ihres JavaScript-Codes erheblich verbessern können. In diesem Artikel tauchen wir tief in diese Konzepte ein, untersuchen bewährte Vorgehensweisen und geben praktische Beispiele, die Ihnen helfen, ihre Verwendung zu meistern.
Currying verstehen
Currying ist eine Technik, bei der eine Funktion in eine Folge von Funktionen umgewandelt wird, von denen jede genau ein Argument entgegennimmt. Dadurch können Sie eine Funktion mit mehreren Argumenten in eine Reihe von unären Funktionen (Funktionen mit einem Argument) aufteilen.
Beispiel für Currying
Betrachten Sie eine einfache Funktion, die drei Zahlen addiert:
function add(a, b, c) {
return a + b + c;
}Wir können diese Funktion in eine gecurryte Version umwandeln:
Erklärung:
- Die Funktion
addnimmt drei Argumente entgegen und gibt ihre Summe zurück. - Die Funktion
curryAddist eine gecurryte Version vonadd. Sie nimmt ein Argumentaentgegen und gibt eine weitere Funktion zurück, diebentgegennimmt. Diese zweite Funktion gibt wiederum eine weitere Funktion zurück, diecentgegennimmt. Die innerste Funktion gibt die Summe vona,bundczurück.
Vorteile von Currying
- Wiederverwendbarkeit: Gecurryte Funktionen ermöglichen es Ihnen, neue Funktionen zu erstellen, indem Sie einige Argumente fest vorgeben. Das erhöht die Wiederverwendbarkeit, da Sie leicht spezialisierte Versionen einer Funktion erstellen können, ohne Code zu duplizieren.
Hier ist curriedAdd eine gecurryte Version der Funktion add. Sie ermöglicht es uns, spezialisierte Funktionen wie add5 zu erstellen, indem wir das erste Argument (a) auf 5 festlegen. Das fördert die Wiederverwendung von Code, da wir mehrere spezialisierte Funktionen erstellen können, ohne die Logik für die Addition zu wiederholen.
- Funktionskomposition: Currying erleichtert das Zusammensetzen von Funktionen. Funktionskomposition ist der Prozess, zwei oder mehr Funktionen zu kombinieren, um eine neue Funktion zu erzeugen.
In diesem Beispiel kombinieren wir die Funktionen multiply und addOne mithilfe von Currying. Durch das Currying dieser Funktionen können wir leicht eine neue Funktion addOneThenMultiplyBy5 erstellen, die zuerst 1 zum Eingabewert (x) addiert und dann das Ergebnis mit 5 multipliziert. Dies zeigt, wie Currying die Funktionskomposition erleichtert und es einfacher macht, neue Funktionen durch die Kombination bestehender Funktionen zu erstellen.
Currying in JavaScript implementieren
Wir können eine Hilfsfunktion erstellen, um jede Funktion zu curryen. Hier ist eine Implementierung einer generischen Currying-Funktion:
Erklärung:
Currying-Funktion (
curry):- Die Funktion
currynimmt eine andere Funktionfnals Eingabe. - Sie gibt eine neue Funktion namens
curriedzurück. - Diese Funktion
curriednimmt mithilfe der Rest-Parameter-Syntax (...args) beliebig viele Argumente entgegen.
- Die Funktion
Gecurryte Funktion (
curried):- Innerhalb von
curriedwird geprüft, ob die Anzahl der übergebenen Argumente (args.length) größer oder gleich der Anzahl der von der ursprünglichen Funktionfnerwarteten Argumente (fn.length) ist. - Wenn genügend Argumente vorhanden sind, ruft sie die ursprüngliche Funktion
fnmit diesen Argumenten überfn.apply(this, args)auf. - Wenn nicht genügend Argumente vorhanden sind, gibt sie eine neue Funktion zurück, die weitere Argumente (
nextArgs) mithilfe des Spread-Operators (...nextArgs) akzeptiert. - Diese neue Funktion rekursiv ruft
curriedmit den kombinierten Argumenten (args.concat(nextArgs)) auf und stellt so sicher, dass alle Argumente schließlich gesammelt werden, bevor die ursprüngliche Funktionfnaufgerufen wird.
Hinweis:
fn.lengthzählt nur Parameter ohne Standardwerte und ignoriert Rest-Parameter.- Innerhalb von
Beispielverwendung:
- Wir definieren eine Funktion
multiply, die drei Argumente entgegennimmt und ihr Produkt zurückgibt. - Wir erstellen eine gecurryte Version der Funktion
multiply, indem wir sie an die Funktioncurryübergeben, die eine neue FunktioncurriedMultiplyzurückgibt. - Jetzt kann
curriedMultiplymit einem, zwei oder drei Argumenten aufgerufen werden. - Jedes Mal, wenn wir
curriedMultiplymit einem Argument oder mehreren Argumenten aufrufen, gibt sie eine neue Funktion zurück, bis alle Argumente gesammelt sind; danach gibt sie das Ergebnis der Multiplikation der Argumente zurück.
- Wir definieren eine Funktion
Partielle Anwendung erkunden
Partielle Anwendung ist eine Technik, bei der Sie eine neue Funktion erstellen, indem Sie einige Argumente der ursprünglichen Funktion vorab belegen. Das ist besonders nützlich, um spezialisierte Funktionen zu erstellen.
Beispiel für partielle Anwendung
Betrachten Sie die folgende Funktion, die eine Nachricht formatiert:
function formatMessage(greeting, name) {
return `${greeting}, ${name}!`;
}Wir können eine partiell angewendete Funktion erstellen:
Erklärung:
- Die Funktion
formatMessagenimmt zwei Argumente,greetingundname, entgegen und gibt eine formatierte Nachricht zurück. - Die Funktion
partialnimmt eine Funktionfnund einige vorab festgelegte Argumente (...presetArgs) entgegen. Sie gibt eine neue Funktion zurück, die die verbleibenden Argumente (...laterArgs) entgegennimmt. - Wenn die neue Funktion aufgerufen wird, kombiniert sie
presetArgsundlaterArgsund ruft die ursprüngliche Funktionfnmit diesen Argumenten auf. - Mit
partialerstellen wirgreetHello, eine Funktion, die immer "Hello" als Begrüßung verwendet. Wenn sie mit einem Namen aufgerufen wird, gibt sie die vollständige Nachricht zurück.
Vorteile der partiellen Anwendung
Vereinfachung: Einfachere Funktionen aus komplexeren erstellen
Angenommen, wir haben eine Funktion, die den Endpreis eines Artikels nach Rabatt und Steuer berechnet.
function calculateFinalPrice(price, discount, tax) {
return price - (price * discount) + (price * tax);
}Diese Funktion benötigt drei Argumente, was die wiederholte Verwendung etwas umständlich macht, wenn Rabatt- und Steuersätze oft gleich sind. Mit partieller Anwendung können wir das vereinfachen.
Im obigen Beispiel ist applyDiscountAndTax eine partiell angewendete Funktion, die die Werte für discount und tax vorab festlegt. Dadurch lässt sich der Endpreis für verschiedene Artikel leichter berechnen, ohne die Rabatt- und Steuersätze jedes Mal erneut angeben zu müssen.
Code-Wiederverwendbarkeit: Häufige Funktionslogik mit unterschiedlichen vorab festgelegten Argumenten wiederverwenden
Stellen Sie sich vor, wir haben eine Funktion, die Nachrichten mit unterschiedlichen Schweregraden protokolliert.
function logMessage(level, message) {
console.log(`[${level}] ${message}`);
}Wir können mithilfe partieller Anwendung wiederverwendbare Funktionen für verschiedene Protokollstufen erstellen.
Hier ist createLogger eine partiell angewendete Funktion, die das Argument level festlegt. Die Funktionen infoLogger und errorLogger können nun verwendet werden, um Nachrichten mit den vorab festgelegten Protokollstufen zu protokollieren und dabei die gemeinsame Logik von logMessage wiederzuverwenden.
- Bessere Lesbarkeit: Macht Code lesbarer, indem komplexe Funktionen aufgeteilt werden Betrachten Sie eine Funktion, die Datumsangaben in verschiedenen Stilen formatiert.
function formatDate(date, format) {
const options = { year: 'numeric', month: '2-digit', day: '2-digit' };
if (format === 'US') {
options.month = 'long';
} else if (format === 'EU') {
options.day = 'numeric';
options.month = 'numeric';
}
return new Date(date).toLocaleDateString(undefined, options);
}Durch partielle Anwendung können wir lesbarere Funktionen für verschiedene Datumsformate erstellen.
createDateFormatter wendet das Argument format partiell an und erzeugt dadurch spezifische Funktionen für US- und EU-Datumsformate. Diese Aufteilung macht den Code lesbarer und leichter verständlich, da jeder Formatter-Funktion ein bestimmtes Format zugeordnet ist.
Diese Beispiele zeigen, wie partielle Anwendung in JavaScript komplexe Funktionen vereinfachen, die Wiederverwendbarkeit des Codes erhöhen und die Lesbarkeit verbessern kann, wodurch der Code leichter zu verwalten und zu verstehen ist.
Best Practices für die Verwendung von Currying und partieller Anwendung
Funktionen rein halten
- Stellen Sie sicher, dass gecurryte und partiell angewendete Funktionen rein bleiben, also ohne Seiteneffekte. Das macht sie leichter nachvollziehbar und testbar.
Nur bei Bedarf einsetzen
- Verwenden Sie Currying und partielle Anwendung dann, wenn sie natürlich zum jeweiligen Problem passen.
- Vermeiden Sie den übermäßigen Einsatz dieser Techniken, da sie den Code schwerer verständlich machen können, wenn sie nicht mit Bedacht verwendet werden.
Funktionskomposition nutzen
- Kombinieren Sie gecurryte Funktionen, um komplexere Funktionalität zu erstellen. Currying funktioniert gut mit Funktionskomposition und führt zu modularerem Code.
Dokumentation und Benennung
- Dokumentieren Sie gecurryte und partiell angewendete Funktionen sorgfältig, um ihre erwartete Verwendung zu verdeutlichen.
- Verwenden Sie klare und aussagekräftige Namen für Funktionen, um ihren Zweck zu vermitteln.
INFO
Wenn Sie Currying und partielle Anwendung häufig verwenden, sollten Sie die Bibliothek Lodash in Betracht ziehen, die praktische Hilfsfunktionen wie _.curry und _.partial bereitstellt.
Mit Array-Methoden kombinieren
Currying lässt sich effektiv mit Array-Methoden wie map, filter und reduce kombinieren, um prägnanten und ausdrucksstarken Code zu schreiben.
Erklärung:
- Die Funktion
curriedMultiplywird verwendet, ummultiplyByTwozu erstellen, eine Funktion, die ihr Argument mit 2 multipliziert. - Das Array
numberswird mitmaptransformiert, wobeimultiplyByTwoauf jedes Element angewendet wird, wodurch ein neues Array mit verdoppelten Zahlen entsteht.
Fazit
Currying und partielle Anwendung in JavaScript bieten leistungsstarke Techniken, um die Funktionskomposition zu vereinfachen, die Wiederverwendbarkeit des Codes zu erhöhen und die Lesbarkeit zu verbessern. Currying wandelt Funktionen mit mehreren Argumenten in eine Folge von Funktionen mit einem Argument um und ermöglicht so flexibleren und modulareren Code. Partielle Anwendung erlaubt es, Funktionsargumente vorab festzulegen, was die Wiederverwendung von Code und die Vereinfachung komplexer Funktionen erleichtert. Durch den Einsatz dieser funktionalen Programmierkonzepte können Entwickler saubereren, prägnanteren und besser wartbaren JavaScript-Code schreiben.
Practice
What is correct about Currying in JavaScript?