תכונת שפת JavaScript זו יכולה לעזור לסדר את הקוד שלך ותעניק לך הערכה חדשה לגבי אופן הפעולה של פונקציות.
פונקציות Curried יכולות לעזור להפוך את קוד ה-JavaScript שלך לקריא ואקספרסיבי יותר. טכניקת הקאריינג היא אידיאלית כאשר אתה רוצה לפרק את ההיגיון המורכב לחתיכות קוד קטנות יותר, עצמאיות וניתנות לניהול.
למד הכל על פונקציות curry ב-JavaScript, כיצד להשתמש בטכניקת curry function כדי ליצור פונקציות מיושמות חלקית, כמו גם מקרי שימוש בחיים האמיתיים הן עבור פונקציות מיושמות והן מיושמות חלקית פונקציות.
מה זה קארי?
קארינג נקרא על שם המתמטיקאי האסקל ב. קארי, והמושג נובע מחשבון למדה. Currying לוקח פונקציה שמקבלת יותר מפרמטר אחד ומפרקת אותה לסדרה של פונקציות חד-פרמטריות. במילים אחרות, פונקציית curried לוקחת רק פרמטר אחד בכל פעם.
דוגמה בסיסית לקאריינג
להלן דוגמה לפונקציית קארי:
functionbuildSandwich(ingredient1) {
return(ingredient2) => {
return(ingredient3) => {
return`${ingredient1},${ingredient2},${ingredient3}`
}
}
}
ה buildSandwich() פונקציה מחזירה פונקציה נוספת - פונקציה אנונימית שמקבלת את ה מרכיב 2 טַעֲנָה. לאחר מכן, פונקציה אנונימית זו מחזירה פונקציה אנונימית נוספת שמקבלת
מרכיב 3. לבסוף, פונקציה אחרונה זו מחזירה את התבנית מילולית, דרך של עיצוב מחרוזות ב-JavaScript.מה שיצרת הוא פונקציה מקוננת שבה כל פונקציה קוראת לזו שמתחתיה עד שנגיע לסוף. עכשיו, כשאתה מתקשר buildSandwich() ותעביר לו פרמטר בודד, זה יחזיר את החלק של הפונקציה שאת הארגומנטים שלו אתה עדיין לא מספק:
console.log(buildSandwich("Bacon"))
אתה יכול לראות מהפלט שbuildSandwich מחזיר פונקציה:
כדי להשלים את קריאת הפונקציה, תצטרך לספק את כל שלושת הארגומנטים:
buildSandwich("Bacon")("Lettuce")("Tomato")
קוד זה מעביר את "בייקון" לפונקציה הראשונה, "חסה" לשנייה, ואת "עגבנייה" לפונקציה האחרונה. במילים אחרות, ה buildSandwich() הפונקציה באמת מחולקת לשלוש פונקציות, כאשר כל פונקציה מקבלת פרמטר אחד בלבד.
למרות שזה תקף לחלוטין לקארי באמצעות הפונקציות המסורתיות, כל הקינון יכול להיות די מכוער ככל שתגיע עמוק יותר. כדי לעקוף את זה, אתה יכול להשתמש בפונקציות החצים ולנצל את התחביר הנקי שלהן:
const buildMeal = ingred1 =>ingred2 =>ingred3 =>
`${ingred1}, ${ingred2}. ${ingred3}`;
גרסה מחודשת זו היא תמציתית יותר, יתרון בשימוש פונקציות חץ לעומת פונקציות רגילות. אתה יכול לקרוא לפונקציה באותו אופן שעשית עם הקודמת:
buildMeal("Bacon")("Lettuce")("Tomato")
פונקציות קארי מיושמות חלקית
פונקציות מיושמות חלקית הן שימוש נפוץ בקאריינג. טכניקה זו כרוכה באספקת הארגומנטים הדרושים בלבד בכל פעם (במקום אספקת כל הארגומנטים). בכל פעם שאתה מפעיל פונקציה על ידי העברת כל הפרמטרים הנדרשים, אתה אומר ש"החלת" את הפונקציה הזו.
בואו נסתכל על דוגמה:
const multiply = (x, y) => x * y;
להלן גרסת הקארי של כפל:
const curriedMultiply = x =>y => x * y;
ה curriedMultiply() הפונקציה מקבלת את איקס ארגומנט עבור הפונקציה הראשונה ו y עבור הפונקציה השנייה, היא מכפילה את שני הערכים.
כדי ליצור את הפונקציה המיושמת חלקית הראשונה, התקשר curriedMultiple() עם הפרמטר הראשון והקצה את הפונקציה המוחזרת למשתנה:
const timesTen = curriedMultiply(10)
בשלב זה, הקוד "החיל באופן חלקי" את curriedMultiply() פוּנקצִיָה. אז בכל פעם שתרצו להתקשר פעמים עשר(), אתה רק צריך להעביר אותו מספר אחד והמספר יוכפל אוטומטית ב-10 (שמאוחסן בתוך הפונקציה המיושמת):
console.log(timesTen(8)) // 80
זה מאפשר לך לבנות על פונקציה מורכבת אחת על ידי יצירת מספר פונקציות מותאמות אישית ממנה, שלכל אחת מהן פונקציונליות משלה נעולה.
תסתכל על דוגמה שקרובה יותר למקרה שימוש אמיתי בפיתוח אתרים. למטה יש לך א updateElemText() פונקציה שלוקחת אלמנט של אלמנט תְעוּדַת זֶהוּת בשיחה הראשונה, התוכן בשיחה השנייה, ולאחר מכן מעדכן את האלמנט בהתבסס על תְעוּדַת זֶהוּת והתוכן שסיפקת לו:
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!")
הרכב פונקציות עם פונקציות קארי
שימוש נפוץ נוסף בקארי הוא הרכב פונקציות. זה מאפשר לך לקרוא לפונקציות קטנות, בסדר מסוים, ולשלב אותן לפונקציה אחת ומורכבת יותר.
לדוגמה, באתר מסחר אלקטרוני היפותטי, הנה שלוש פונקציות שאולי תרצה להפעיל בזו אחר זו (בסדר מדויק):
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.`);
}
שימו לב שקוד זה משתמש ב- לתת מילת מפתח כדי להגדיר את completeOrder() פוּנקצִיָה. זה מאפשר לך להקצות מחדש ערך למשתנה והוא חלק ממנו כיצד פועלת scoping ב-JavaScript.
לאחר מכן, עליך לקרוא לפונקציות בסדר הפוך (מבפנים החוצה) מכיוון שתרצה להוסיף את הלקוחות תחילה:
completeOrder = (processOrder(completeOrder));
completeOrder = (addCustomer(completeOrder));
completeOrder("1000")
זה ייתן לך את הפלט הבא:
אם היית כותב את הפונקציות לעיל בצורה הרגילה, הקוד ייראה בערך כך:
functionaddCustomer(...args) {
returnfunctionprocessOrder(...args) {
returnfunctioncompleteOrder(...args) {
// end
}
}
}
כשאתה מתקשר ל addCustomer() פונקציה והעברת הארגומנטים, אתה מתחיל מבפנים ויוצא החוצה לראש הפונקציה.
המר פונקציה רגילה לפונקציה קארי עם פונקציית קארי
אם אתה מתכנן להשתמש הרבה בפונקציות קארי, אתה יכול לייעל את התהליך עם פונקציית עוזר.
פונקציה זו תמיר כל פונקציה רגילה לפונקציה curried. הוא משתמש ברקורסיה כדי לטפל בכל מספר של ארגומנטים.
const curry = (fn) => {
return curried = (...args) => {
if (fn.length !== args.length) {
return curried.bind(null, ...args)
}
return fn(...args);
}
}
פונקציה זו תקבל כל פונקציה כתובה סטנדרטית שמקבלת יותר מפרמטר אחד, ומחזירה גרסה מטורפת של אותה פונקציה. כדי לראות את זה בפעולה, השתמש בפונקציה לדוגמה זו שלוקחת שלושה פרמטרים ומוסיפה אותם יחד:
const total = (x, y, z) => x + y + z
כדי להמיר פונקציה זו, התקשר ל- קָארִי() לתפקד ולעבור סה"כ בתור טיעון:
const curriedTotal = curry(total)
עכשיו כדי לקרוא לפונקציה, אתה רק צריך להעביר את כל הארגומנטים:
console.log(curriedTotal(10)(20)(30)) // 60
עוד על פונקציות ב-JavaScript
הפונקציות של JavaScript הן גמישות ביותר ופונקציות קשות הן רק חלק קטן מזה. ישנם סוגים רבים אחרים של פונקציות כמו פונקציות חץ, פונקציות בנאי ופונקציות אנונימיות. היכרות עם פונקציות אלה ומרכיביהן היא המפתח לשליטה ב-JavaScript.