במאמר הקודם דיברנו על קלאסים ב-EcmaScript 6 ובחרתי לתת למאמר כותרת 'קלאסים בקלאסה' – כי בדיחות אבא זה אני. הפעם, במאמר הזה אני אדבר על פונקציות למדא בג'אווהסקריפט (כתוב Lambda אבל מבטאים את זה כלמדא) ולמרות שממש ממש ממש התפתיתי, לא כתבתי בכותרת משחק מילים עבש שמתייחס ללמבדה. הריקוד הלטיני המפורסם.
אז מה זו פונקצית למדא? אם נפתח את ויקיפדיה או הספר המאובק ללימוד מדעי המחשב, נגלה שפונקצית למדא היא דרך להגדיר פונקציה אנונימית (כלומר ללא שם) והיא שימושית במיוחד כאשר רוצים להגדיר פונקציה שמחזירה פונקציה.
טוב, זה נשמע אינטואיטיבי כמו הנדסה גרעינית, אבל האמת היא שזה די קל ופשוט ואני אף אדגים. בואו ונגיד שאני רוצה להכניס למשתנה a את הסכימה של שני מספרים. למשל 1 ו-2. עם ECMAScript 5, אני עושה את זה עם הפונקציה הפשוטה הזו:
var sum = function (arg1, arg2) {
var result = arg1 + arg2;
console.log(result);
}
let a = sum(1,2); //3
ב-ECMAScript 6 אני יכול לעשות את זה עם פונקצית למדא, כלומר משהו כזה:
let sum = (arg1, arg2) => { console.log( arg1 + arg2) };
let a = sum(1,2); //3
נראה משהו פשוט ואידיוטי, נכון? טוב, זה יכול לחסוך שורה או שתיים, אבל למה צריך את זה בדיוק? יש כמה תשובות לזה. הראשונה היא שפונקצית למדא שימושית מאוד כאשר אנחנו בונים אובייקטים ב-JavaScript. בניית אובייקטים של JSON מסוגים שונים היא קריטית באפליקצית JavaScript שהיא לא hello world. נניח ואנחנו צריכים ליצור אובייקט שיש בו id ו-name. ב-ECMAScript 5, זה יראה ככה:
var setObject = function (id, name) {
return {
id: id,
name: name
};
};
setObject (4, "Moshe"); //Object {id: 4, name: "Moshe"}
ואיך זה יראה עם שימוש בפונקצית למדא, ממש ככה:
var setObject = (id, name) => ({ id: id, name: name });
setObject (4, "Moshe"); //Object {id: 4, name: "Moshe"}
וזה משהו שנראה יותר טוב, נכון?
בואו ונמשיך – בוא נדמיין שיש לי מערך שמכיל אובייקטים של טלפונים, משהו בסגנון הזה:
var phones = [
{ name:'iphone', price:9999 },
{ name:'Android', price:200 },
{ name:'Nokia 4ever', price:1 }
];
אני צריך לכתוב פונקציה שתוציא רק את מחירי הטלפונים. זו משימה שמתרחשת המון באפליקצית JS. עוברים על אובייקט ולוקחים רק משהו אחד מתוכו. איך עושים את זה? משתמשים בפונקצית map (לא להבהל, זו פשוט פונקציה שעוברת על כל איבר במערך) ועושים משהו כזה:
var prices = phones.map(
function(phone) {
return phone.price;
}
);
console.log(prices); // [9999, 200, 1]
בואו ונשווה את זה לפונקצית למדא של ECMAScript 6:
var phones = [
{ name:'iphone', price:9999 },
{ name:'Android', price:200 },
{ name:'Nokia 4ever', price:1 }
];
var prices = phones.map(phone => phone.price);
console.log(prices); // [9999, 200, 1]
וזה כבר נראה הרבה הרבה יותר טוב וגם יותר אינטואיטיבי. פשוט צריך לזכור – איפה שיש פונקציה אנונימית, אנחנו יכולים לשים פונקצית חץ. וזה שימושי מאוד בכל פונקצית map או filter שמשתמשים בהן המון. במקום לבנות for each או לולאת for, אפשר להשתמש בזה. וזה ממש נהדר.
זה שימושי גם בחגיגת קולבקים או promise. הנה דוגמה שלא אני כתבתי אבל היא שימושית מאוד להבנת הרעיון:
// ES5
aAsync().then(function() {
returnbAsync();
}).then(function() {
returncAsync();
}).done(function() {
finish();
});
// ES6
aAsync().then(() => bAsync()).then(() => cAsync()).done(() => finish);
אבל אחד הכוחות החזקים ביותר של פונקצית למדא הוא ה-lexical this. כל מי שכתב JavaScript יודע שה-this מאבד ממשמעותו בכל פעם ובגלל זה אנחנו צריכים פטנטים טפשיים של this=that ואני אדגים:
function FooCtrl (FooService) {
var that = this;
that.foo = 'Hello';
FooService
.doSomething(function (response) {
that.foo = response;
});
}
ברגע שאנחנו מעבירים פונקציה אנונימית (מאוד אופייני ל-callbacks) מתוך פונקציה אחרת (במקרה הזה אנחנו קוראים ל-doSomething מתוך FooCtrl , ה-this מאבד את הקונטקסט לקונטקס של הפונקציה שלה אנחנו קוראים. בגלל זה אנחנו צריכים להעביר את משתנה ה-this למקום אחר. במקרה הזה ל-that. עם פונקצית למדא, ה-this נשאר ה-this של הפונקציה שקראה לו ואנחנו יכולים לעשות משהו כזה:
function FooCtrl (FooService) {
this.foo = 'Hello';
FooService
.doSomething((response) => { // woo, pretty
this.foo = response;
});
}
אני יודע שזה די מבלבל. אבל בגדול, איפה שאתם רואים פונקציה אנונימית, סימן שאפשר להמיר אותה בפונקצית למדא ומרוויחים המון אם זו פונקצית map או filter. אם אנחנו צריכים ליצור אובייקט מאובייקטים אחרים או מאפס, פונקצית למדא היא פתרון נהדר. אם אנחנו נאלצים להשתמש ב-that כחלק מ-promise או callbac, אפשר לשקול להשתמש בלמדא.
תגובה אחת
בדוגמא הראשונה שהבאת,
var sum = function (arg1, arg2) {
var result = arg1 + arg2;
console.log(result);
}
let a = sum(1,2); //3
console.log(a) יחזיר undefined, בגלל שהפונקציה sum לא מחזירה שום ערך.
לא עדיף לכתוב פשוט sum(1,2) במקום להגדיר את זה בתור ערך של משתנה?