Denne JavaScript-sprogfunktion kan hjælpe med at rydde op i din kode og vil give dig en ny forståelse af, hvordan funktioner fungerer.

Curried-funktioner kan hjælpe med at gøre din JavaScript-kode mere læsbar og udtryksfuld. Curry-teknikken er ideel, når du vil nedbryde kompleks logik i mindre, selvstændige, mere håndterbare stykker kode.

Lær alt om curry-funktioner i JavaScript, hvordan du bruger funktionen currying-teknikken til at skabe delvist anvendte funktioner, såvel som virkelige use cases for både curry-funktioner og delvist anvendte funktioner.

Hvad er karry?

Currying er opkaldt efter matematikeren Haskell B. Karry, og konceptet stammer fra Lambda-regning. Currying tager en funktion, der modtager mere end én parameter, og opdeler den i en række unære (én-parameter) funktioner. Med andre ord tager en curried-funktion kun én parameter ad gangen.

Et grundlæggende eksempel på karryning

Nedenfor er et eksempel på en karryfunktion:

functionbuildSandwich(ingredient1) {
return(ingredient2) => {
return(ingredient3) => {
return`${ingredient1},${ingredient2},${ingredient3}`
}
}
}
instagram viewer

Det buildSandwich() funktion returnerer en anden funktion — en anonym funktion, der modtager ingrediens 2 argument. Derefter returnerer denne anonyme funktion en anden anonym funktion, der modtager ingrediens 3. Endelig returnerer denne sidste funktion skabelonen literal, en måde at formateringsstrenge i JavaScript.

Det, du har oprettet, er en indlejret funktion, hvor hver funktion kalder den, der er under den, indtil vi når slutningen. Nu, når du ringer buildSandwich() og sender den en enkelt parameter, returnerer den den del af funktionen, hvis argumenter du endnu ikke har angivet:

console.log(buildSandwich("Bacon"))

Du kan se fra outputtet, at buildSandwich returnerer en funktion:

For at fuldføre funktionskaldet skal du angive alle tre argumenter:

buildSandwich("Bacon")("Lettuce")("Tomato")

Denne kode sender "Bacon" til den første funktion, "Salat" til den anden og "Tomat" til den sidste funktion. Med andre ord buildSandwich() funktion er virkelig opdelt i tre funktioner, hvor hver funktion kun modtager én parameter.

Selvom det er helt gyldigt at bruge karry ved hjælp af de traditionelle funktioner, kan al nesting blive ret grimt, jo dybere du kommer. For at komme uden om dette kan du bruge pilefunktioner og drage fordel af deres renere syntaks:

const buildMeal = ingred1 =>ingred2 =>ingred3 =>
`${ingred1}, ${ingred2}. ${ingred3}`;

Denne refactored version er mere kortfattet, en fordel ved at bruge pilefunktioner vs almindelige funktioner. Du kan kalde funktionen på samme måde, som du gjorde med den forrige:

buildMeal("Bacon")("Lettuce")("Tomato")

Delvist anvendte karryfunktioner

Delvist anvendte funktioner er en almindelig brug af currying. Denne teknik indebærer kun at levere de nødvendige argumenter ad gangen (i stedet for at levere alle argumenterne). Når du kalder en funktion ved at sende alle de nødvendige parametre, siger du, at du har "anvendt" den funktion.

Lad os se på et eksempel:

const multiply = (x, y) => x * y;

Nedenfor er den karryerede version af multiplicere:

const curriedMultiply = x =>y => x * y;

Det curriedMultiply() funktionen modtager x argument for den første funktion og y for den anden funktion multiplicerer den begge værdier.

For at oprette den første delvist anvendte funktion, ring curriedMultiple() med den første parameter og tildel den returnerede funktion til en variabel:

const timesTen = curriedMultiply(10)

På dette tidspunkt har koden "delvist anvendt". curriedMultiply() fungere. Så når som helst du vil ringe gange ti(), du skal blot give det et tal, og tallet vil automatisk blive ganget med 10 (som er gemt i den anvendte funktion):

console.log(timesTen(8)) // 80

Dette lader dig bygge på en enkelt kompleks funktion ved at oprette flere brugerdefinerede funktioner fra den, hver med sin egen funktionalitet låst ind.

Tag et kig på et eksempel, der er tættere på en rigtig webudviklingsbrugssag. Nedenfor har du en updateElemText() funktion, der tager et elements id på det første opkald, indholdet på det andet opkald, og derefter opdaterer elementet baseret på id og indhold, du har leveret:

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!")

Funktionssammensætning med curried-funktioner

En anden almindelig anvendelse af karry er funktionssammensætning. Dette lader dig kalde små funktioner i en bestemt rækkefølge og kombinere dem til en enkelt, mere kompleks funktion.

For eksempel på et hypotetisk e-handelswebsted er her tre funktioner, som du måske ønsker at køre efter hinanden (i præcis rækkefølge):

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.`);
}

Bemærk, at denne kode bruger lade nøgleord til at definere completeOrder() fungere. Dette giver dig mulighed for at gentildele en værdi til variablen og er en del af hvordan scoping fungerer i JavaScript.

Dernæst skal du kalde funktionerne i omvendt rækkefølge (indefra og ud), fordi du vil tilføje kunderne først:

completeOrder = (processOrder(completeOrder));
completeOrder = (addCustomer(completeOrder));
completeOrder("1000")

Dette vil give dig følgende output:

Hvis du skulle skrive ovenstående funktioner på den almindelige måde, vil koden se sådan ud:

functionaddCustomer(...args) {
returnfunctionprocessOrder(...args) {
returnfunctioncompleteOrder(...args) {
// end
}
}
}

Når du ringer til addCustomer() funktion og videregive argumenterne, starter du indefra og arbejder dig ud til toppen af ​​funktionen.

Konverter en normal funktion til en karryfunktion med en karryfunktion

Hvis du planlægger at bruge karryfunktioner meget, kan du strømline processen med en hjælpefunktion.

Denne funktion vil konvertere enhver normal funktion til en curried funktion. Den bruger rekursion til at håndtere et vilkårligt antal argumenter.

const curry = (fn) => {
return curried = (...args) => {
if (fn.length !== args.length) {
return curried.bind(null, ...args)
}

return fn(...args);
}
}

Denne funktion vil acceptere enhver skriftlig standardfunktion, der modtager mere end én parameter, hvilket returnerer en curried version af denne funktion. For at se det i aktion, brug denne eksempelfunktion, der tager tre parametre og tilføjer dem sammen:

const total = (x, y, z) => x + y + z

For at konvertere denne funktion skal du kalde karry() funktion og bestå Total som argument:

const curriedTotal = curry(total)

For nu at kalde funktionen skal du blot sende alle argumenterne ind:

console.log(curriedTotal(10)(20)(30)) // 60

Mere om funktioner i JavaScript

JavaScripts funktioner er ekstremt fleksible, og kurrende funktioner er kun en lille del af det. Der er mange andre typer funktioner som pilefunktioner, konstruktørfunktioner og anonyme funktioner. At gøre dig bekendt med disse funktioner og deres komponenter er nøglen til at mestre JavaScript.