Diese JavaScript-Sprachfunktion kann Ihnen helfen, Ihren Code aufzuräumen und Ihnen ein neues Verständnis für die Funktionsweise von Funktionen zu vermitteln.
Curry-Funktionen können dazu beitragen, Ihren JavaScript-Code lesbarer und ausdrucksvoller zu machen. Die Currying-Technik ist ideal, wenn Sie komplexe Logik in kleinere, eigenständige und besser verwaltbare Codeteile zerlegen möchten.
Erfahren Sie alles über Curry-Funktionen in JavaScript und wie Sie die Funktions-Curry-Technik zum Erstellen verwenden teilweise angewandte Funktionen sowie reale Anwendungsfälle sowohl für Curry-Funktionen als auch für teilweise angewandte Funktionen.
Was ist Curry?
Currying ist nach dem Mathematiker Haskell B. benannt. Curry, und das Konzept leitet sich aus der Lambda-Kalküle ab. Currying nimmt eine Funktion, die mehr als einen Parameter empfängt, und zerlegt sie in eine Reihe unärer (Ein-Parameter-)Funktionen. Mit anderen Worten: Eine Curry-Funktion benötigt jeweils nur einen Parameter.
Ein einfaches Beispiel für Currying
Unten finden Sie ein Beispiel für eine Curry-Funktion:
functionbuildSandwich(ingredient1) {
return(ingredient2) => {
return(ingredient3) => {
return`${ingredient1},${ingredient2},${ingredient3}`
}
}
}
Der buildSandwich() Die Funktion gibt eine andere Funktion zurück – eine anonyme Funktion, die die empfängt Zutat2 Streit. Dann gibt diese anonyme Funktion eine andere anonyme Funktion zurück, die empfängt Zutat3. Schließlich gibt diese letzte Funktion das Vorlagenliteral zurück Formatieren von Zeichenfolgen in JavaScript.
Was Sie erstellt haben, ist eine verschachtelte Funktion, bei der jede Funktion die darunter liegende Funktion aufruft, bis wir das Ende erreichen. Wenn Sie jetzt anrufen buildSandwich() und ihm einen einzelnen Parameter übergeben, wird der Teil der Funktion zurückgegeben, dessen Argumente Sie noch angeben müssen:
console.log(buildSandwich("Bacon"))
Sie können der Ausgabe entnehmen, dass buildSandwich eine Funktion zurückgibt:
Um den Funktionsaufruf abzuschließen, müssen Sie alle drei Argumente angeben:
buildSandwich("Bacon")("Lettuce")("Tomato")
Dieser Code übergibt „Bacon“ an die erste Funktion, „Lettuce“ an die zweite und „Tomato“ an die letzte Funktion. Mit anderen Worten, die buildSandwich() Die Funktion ist eigentlich in drei Funktionen unterteilt, wobei jede Funktion nur einen Parameter erhält.
Während es völlig in Ordnung ist, mit den traditionellen Funktionen zu curryen, kann die ganze Verschachtelung ziemlich hässlich werden, je tiefer man vordringt. Um dies zu umgehen, können Sie Pfeilfunktionen verwenden und deren sauberere Syntax nutzen:
const buildMeal = ingred1 =>ingred2 =>ingred3 =>
`${ingred1}, ${ingred2}. ${ingred3}`;
Diese überarbeitete Version ist prägnanter, ein Vorteil der Verwendung Pfeilfunktionen vs. reguläre Funktionen. Sie können die Funktion auf die gleiche Weise aufrufen wie die vorherige:
buildMeal("Bacon")("Lettuce")("Tomato")
Teilweise angewendete Curry-Funktionen
Teilweise angewendete Funktionen sind eine häufige Verwendung von Currying. Bei dieser Technik werden jeweils nur die benötigten Argumente bereitgestellt (anstatt alle Argumente bereitzustellen). Immer wenn Sie eine Funktion aufrufen, indem Sie alle erforderlichen Parameter übergeben, sagen Sie, dass Sie diese Funktion „angewandt“ haben.
Schauen wir uns ein Beispiel an:
const multiply = (x, y) => x * y;
Unten ist die Curry-Version von Multiply:
const curriedMultiply = x =>y => x * y;
Der curriedMultiply() Funktion empfängt die X Argument für die erste Funktion und j Für die zweite Funktion werden dann beide Werte multipliziert.
Um die erste teilweise angewendete Funktion zu erstellen, rufen Sie auf curriedMultiple() mit dem ersten Parameter und weisen Sie die zurückgegebene Funktion einer Variablen zu:
const timesTen = curriedMultiply(10)
Zu diesem Zeitpunkt wurde der Code „teilweise angewendet“. curriedMultiply() Funktion. Sie können also jederzeit anrufen timesTen(), Sie müssen ihm nur eine Zahl übergeben und die Zahl wird automatisch mit 10 multipliziert (was in der angewendeten Funktion gespeichert wird):
console.log(timesTen(8)) // 80
Auf diese Weise können Sie auf einer einzelnen komplexen Funktion aufbauen, indem Sie daraus mehrere benutzerdefinierte Funktionen erstellen, von denen jede über ihre eigene Funktionalität verfügt.
Schauen Sie sich ein Beispiel an, das einem echten Anwendungsfall für die Webentwicklung näher kommt. Unten haben Sie eine updateElemText() Funktion, die ein Element übernimmt Ausweis beim ersten Aufruf den Inhalt beim zweiten Aufruf und aktualisiert dann das Element basierend auf dem Ausweis und Inhalt, den Sie bereitgestellt haben:
const updateElemText = id = content
=> document.querySelector(`#${id}`).textContent = content// Lock the element's id into the function:
const updateHeaderText = updateElemText('header')
// Update the header text
updateHeaderText("Hello World!")
Funktionskomposition mit Curry-Funktionen
Eine weitere häufige Verwendung von Curry ist die Funktionskomposition. Auf diese Weise können Sie kleine Funktionen in einer bestimmten Reihenfolge aufrufen und sie zu einer einzigen, komplexeren Funktion kombinieren.
In einer hypothetischen E-Commerce-Website sind beispielsweise die folgenden drei Funktionen aufgeführt, die Sie nacheinander (in präziser Reihenfolge) ausführen möchten:
const addCustomer = fn =>(...args) => {
console.log("Saving customer info")
return fn(...args)
}const processOrder = fn =>(...args) => {
console.log(`processing order #${args[0]}`)
return fn(...args);
}
let completeOrder = (...args) => {
console.log(`Order #${[...args].toString()} completed.`);
}
Beachten Sie, dass dieser Code das verwendet lassen Schlüsselwort zum Definieren des Bestellung abschließen() Funktion. Dadurch können Sie der Variablen einen Wert neu zuweisen und sind Teil davon wie Scoping in JavaScript funktioniert.
Als Nächstes müssen Sie die Funktionen in umgekehrter Reihenfolge (von innen nach außen) aufrufen, da Sie zuerst die Kunden hinzufügen möchten:
completeOrder = (processOrder(completeOrder));
completeOrder = (addCustomer(completeOrder));
completeOrder("1000")
Dadurch erhalten Sie die folgende Ausgabe:
Wenn Sie die oben genannten Funktionen auf normale Weise schreiben würden, würde der Code etwa so aussehen:
functionaddCustomer(...args) {
returnfunctionprocessOrder(...args) {
returnfunctioncompleteOrder(...args) {
// end
}
}
}
Wenn Sie anrufen addCustomer() Funktion hinzufügen und die Argumente übergeben, beginnen Sie von innen und arbeiten sich nach außen bis zum Anfang der Funktion vor.
Konvertieren Sie eine normale Funktion mit einer Curry-Funktion in eine Curry-Funktion
Wenn Sie Curry-Funktionen häufig verwenden möchten, können Sie den Prozess mit einer Hilfsfunktion optimieren.
Diese Funktion wandelt jede normale Funktion in eine Curry-Funktion um. Es verwendet Rekursion, um eine beliebige Anzahl von Argumenten zu verarbeiten.
const curry = (fn) => {
return curried = (...args) => {
if (fn.length !== args.length) {
return curried.bind(null, ...args)
}
return fn(...args);
}
}
Diese Funktion akzeptiert jede standardmäßig geschriebene Funktion, die mehr als einen Parameter empfängt, und gibt eine Curry-Version dieser Funktion zurück. Um es in Aktion zu sehen, verwenden Sie diese Beispielfunktion, die drei Parameter nimmt und sie addiert:
const total = (x, y, z) => x + y + z
Um diese Funktion zu konvertieren, rufen Sie die auf Curry() Funktion und Pass gesamt als Argument:
const curriedTotal = curry(total)
Um nun die Funktion aufzurufen, müssen Sie nur noch alle Argumente übergeben:
console.log(curriedTotal(10)(20)(30)) // 60
Mehr über Funktionen in JavaScript
Die Funktionen von JavaScript sind äußerst flexibel und Currying-Funktionen sind nur ein kleiner Teil davon. Es gibt viele andere Arten von Funktionen wie Pfeilfunktionen, Konstruktorfunktionen und anonyme Funktionen. Sich mit diesen Funktionen und ihren Komponenten vertraut zu machen, ist der Schlüssel zur Beherrschung von JavaScript.