Deze JavaScript-taalfunctie kan u helpen uw code op te ruimen en geeft u een nieuwe waardering voor hoe functies werken.
Curried-functies kunnen ervoor zorgen dat uw JavaScript-code leesbaarder en expressiever wordt. De currying-techniek is ideaal als u complexe logica wilt opsplitsen in kleinere, op zichzelf staande, beter beheersbare stukjes code.
Leer alles over curried-functies in JavaScript en hoe u de functie-curry-techniek kunt gebruiken om te creëren gedeeltelijk toegepaste functies, evenals praktijkvoorbeelden voor zowel curried functies als gedeeltelijk toegepaste functies functies.
Wat is curryen?
Currying is vernoemd naar wiskundige Haskell B. Curry, en het concept is afgeleid van Lambda-calculus. Currying neemt een functie die meer dan één parameter ontvangt en verdeelt deze in een reeks unaire functies (één parameter). Met andere woorden: een gecurryde functie gebruikt slechts één parameter tegelijk.
Een basisvoorbeeld van curryen
Hieronder ziet u een voorbeeld van een curried-functie:
functionbuildSandwich(ingredient1) {
return(ingredient2) => {
return(ingredient3) => {
return`${ingredient1},${ingredient2},${ingredient3}`
}
}
}
De buildSandwich() function retourneert een andere functie: een anonieme functie die de ingrediënt2 argument. Vervolgens retourneert deze anonieme functie een andere anonieme functie die ontvangt ingrediënt3. Ten slotte retourneert deze laatste functie de sjabloon letterlijk, een manier van tekenreeksen opmaken in JavaScript.
Wat je hebt gemaakt is een geneste functie waarbij elke functie de functie eronder aanroept totdat we het einde bereiken. Nu, als je belt buildSandwich() en geef het een enkele parameter door, het retourneert het deel van de functie waarvan je de argumenten nog moet opgeven:
console.log(buildSandwich("Bacon"))
Je kunt aan de uitvoer zien dat buildSandwich een functie retourneert:
Om de functieaanroep te voltooien, moet u alle drie de argumenten opgeven:
buildSandwich("Bacon")("Lettuce")("Tomato")
Deze code geeft "Bacon" door aan de eerste functie, "Sla" aan de tweede en "Tomaat" aan de laatste functie. Met andere woorden: de buildSandwich() De functie is eigenlijk opgedeeld in drie functies, waarbij elke functie slechts één parameter ontvangt.
Hoewel het prima is om te curryen met de traditionele functies, kan het nesten behoorlijk lelijk worden naarmate je dieper komt. Om dit te omzeilen, kunt u pijlfuncties gebruiken en profiteren van hun schonere syntaxis:
const buildMeal = ingred1 =>ingred2 =>ingred3 =>
`${ingred1}, ${ingred2}. ${ingred3}`;
Deze gerefactorde versie is beknopter, een voordeel van het gebruik pijlfuncties versus reguliere functies. U kunt de functie op dezelfde manier aanroepen als bij de vorige:
buildMeal("Bacon")("Lettuce")("Tomato")
Gedeeltelijk toegepaste curryfuncties
Gedeeltelijk toegepaste functies zijn een veelgebruikt gebruik van currying. Deze techniek houdt in dat alleen de benodigde argumenten tegelijk worden opgegeven (in plaats van alle argumenten). Telkens wanneer u een functie aanroept door alle vereiste parameters door te geven, zegt u dat u die functie hebt "toegepast".
Laten we eens kijken naar een voorbeeld:
const multiply = (x, y) => x * y;
Hieronder vindt u de curried-versie van vermenigvuldigen:
const curriedMultiply = x =>y => x * y;
De curriedVermenigvuldigen() functie ontvangt de X argument voor de eerste functie en j voor de tweede functie vermenigvuldigt deze beide waarden.
Om de eerste gedeeltelijk toegepaste functie te creëren, roept u aan curriedMeerdere() met de eerste parameter en wijs de geretourneerde functie toe aan een variabele:
const timesTen = curriedMultiply(10)
Op dit punt heeft de code de curriedVermenigvuldigen() functie. Dus wanneer u maar wilt bellen keerTen(), u hoeft slechts één getal door te geven en het getal wordt automatisch vermenigvuldigd met 10 (wat wordt opgeslagen in de toegepaste functie):
console.log(timesTen(8)) // 80
Hierdoor kunt u voortbouwen op één enkele complexe functie door er meerdere aangepaste functies van te maken, elk met zijn eigen functionaliteit.
Bekijk een voorbeeld dat dichter bij een echte webontwikkelingstoepassing ligt. Hieronder heb je een updateElemText() functie die een element nodig heeft ID kaart bij de eerste oproep, de inhoud bij de tweede oproep, en werkt vervolgens het element bij op basis van de ID kaart en de inhoud die u heeft aangeleverd:
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!")
Functiesamenstelling met gecurryde functies
Een ander veelgebruikt gebruik van currying is het samenstellen van functies. Hiermee kunt u kleine functies in een specifieke volgorde oproepen en deze combineren tot één enkele, complexere functie.
Op een hypothetische e-commercewebsite zijn hier bijvoorbeeld drie functies die u mogelijk na elkaar wilt uitvoeren (in precieze volgorde):
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.`);
}
Merk op dat deze code de laten trefwoord om de te definiëren Maak bestelling af() functie. Hiermee kunt u opnieuw een waarde aan de variabele toewijzen en er deel van uitmaken hoe scoping werkt in JavaScript.
Vervolgens moet u de functies in omgekeerde volgorde oproepen (van binnen naar buiten), omdat u eerst de klanten wilt toevoegen:
completeOrder = (processOrder(completeOrder));
completeOrder = (addCustomer(completeOrder));
completeOrder("1000")
Dit geeft je de volgende uitvoer:
Als u de bovenstaande functies op de normale manier schrijft, ziet de code er ongeveer zo uit:
functionaddCustomer(...args) {
returnfunctionprocessOrder(...args) {
returnfunctioncompleteOrder(...args) {
// end
}
}
}
Wanneer u belt met de klant toevoegen() function en geef de argumenten door, je begint van binnenuit en werkt je een weg naar de top van de functie.
Converteer een normale functie naar een curried-functie met een curry-functie
Als u van plan bent veel curried-functies te gebruiken, kunt u het proces stroomlijnen met een helperfunctie.
Deze functie converteert elke normale functie naar een curried-functie. Het maakt gebruik van recursie om een willekeurig aantal argumenten te verwerken.
const curry = (fn) => {
return curried = (...args) => {
if (fn.length !== args.length) {
return curried.bind(null, ...args)
}
return fn(...args);
}
}
Deze functie accepteert elke standaard geschreven functie die meer dan één parameter ontvangt, en retourneert een gecureerde versie van die functie. Om het in actie te zien, gebruikt u deze voorbeeldfunctie, waarbij u drie parameters gebruikt en deze bij elkaar optelt:
const total = (x, y, z) => x + y + z
Om deze functie te converteren, roept u de kerrie() functioneren en passeren totaal als argument:
const curriedTotal = curry(total)
Om de functie nu aan te roepen, hoeft u alleen maar alle argumenten door te geven:
console.log(curriedTotal(10)(20)(30)) // 60
Meer over functies in JavaScript
De functies van JavaScript zijn uiterst flexibel en curryfuncties vormen daar slechts een klein onderdeel van. Er zijn veel andere soorten functies, zoals pijlfuncties, constructorfuncties en anonieme functies. Vertrouwd raken met deze functies en hun componenten is de sleutel tot het beheersen van JavaScript.