פונקציה היא רצף צעדים עם שם
בכל פעם שרוצים לתת שם לחתיכת לוגיקה ולהשתמש בה שוב, כותבים פונקציה. הדרך הוותיקה והפשוטה ביותר ב-JavaScript היא הצהרת פונקציה (function declaration): מילת המפתח function ואחריה שם.
בואו נפרק את זה:
functionהיא מילת המפתח שפותחת הצהרה.greetהוא שם הפונקציה.(name)היא רשימת הפרמטרים: הקלטים שהפונקציה מקבלת.- הבלוק שבתוך הסוגריים המסולסלים הוא גוף הפונקציה.
greet("Ada")היא קריאה. JavaScript מריצה את הגוף כש-nameמקושר ל-"Ada".
הגדרת פונקציה לא מריצה אותה. הקריאה לה היא שמריצה אותה.
פרמטרים וארגומנטים
המילה פרמטר היא השם שבתוך הגדרת הפונקציה. המילה ארגומנט היא הערך שמעבירים בזמן הקריאה. בדיבור יומיומי משתמשים בהן כמילים נרדפות, אבל ההבחנה חשובה כשקוראים הודעות שגיאה.
כאן base ו-exponent הם פרמטרים. 2 ו-10 הם ארגומנטים. JavaScript מקשרת אותם לפי הסדר: הארגומנט הראשון לפרמטר הראשון, וכן הלאה.
בניגוד לשפות אחרות, JavaScript לא תתלונן אם מעבירים מספר לא נכון של ארגומנטים. ארגומנטים חסרים הופכים ל-undefined, ועודפים פשוט מתעלמים מהם בשקט. זה גמיש, ולפעמים מלכודת. בהמשך נראה ערכי ברירת מחדל ופרמטרי rest.
return מחזירה ערך
console.log כותבת לפלט. return מחזירה ערך למי שקרא לפונקציה, כדי שיוכל להשתמש בו:
בלי return, פונקציה מחזירה undefined:
return גם יוצאת מהפונקציה מיד. החזרה מוקדמת היא הדרך המקובלת לטפל במקרי קצה לפני הלוגיקה הראשית:
החזרות מוקדמות מונעות מהגוף הראשי להפוך לפירמידה של if/else.
Hoisting: אפשר לקרוא לפונקציה לפני שהגדרתם אותה
הנה משהו שבאמת מפתיע אנשים שמגיעים משפות אחרות. הצהרות פונקציה עוברות hoisting: JavaScript מעבירה אותן לראש ה-scope שלהן לפני שהיא מריצה קוד כלשהו. כלומר, אפשר לקרוא לפונקציה בשורה שנמצאת מעל המקום שבו הוצהרה:
הקוד הזה רץ בלי בעיה. לפני ההרצה המנוע סורק את ה-scope, רושם את square כפונקציה, ורק אז מתחיל להריץ את הפקודות מלמעלה למטה.
זה הבדל התנהגותי אמיתי בין הצהרות פונקציה לדרכים האחרות ליצור פונקציה (ביטויי פונקציה, arrow functions). אלה עוברים hoisting כמו משתנים: ה_שם_ ידוע, אבל הערך לא מוצב עד שהשורה רצה. עוד על ההבחנה הזאת בחלק הבא.
רוב מדריכי הסגנון ממליצים להגדיר פונקציות לפני שקוראים להן בכל מקרה. Hoisting הוא רשת ביטחון, לא סגנון שכדאי להישען עליו.
הצהרות מול ביטויים
הצהרת פונקציה עומדת בפני עצמה כפקודה. ביטוי פונקציה מופיע במקום שבו מצופה ערך, לרוב בצד הימני של השמה:
שתיהן מייצרות פונקציות שאפשר לקרוא להן. ההבדלים:
- הצהרות עוברות hoisting במלואן. ביטויים פועלים לפי כללי ה-hoisting של המשתנה שאליו הם מוצבים (
constו-letנמצאים ב-temporal dead zone עד שהשורה רצה). - להצהרות חייב להיות שם. ביטויים יכולים להיות אנונימיים, אם כי מתן שם עוזר ב-stack traces.
- הצהרות לא יכולות להופיע בכל מקום. ב-strict mode,
function foo() {}בתוך בלוקifמתנהגת באופן לא עקבי בין מנועים שונים, אז השתמשו שם בביטוי.
לרוב פונקציות העזר ברמה העליונה של קובץ, הצהרה נקראת טוב. לפונקציות שמועברות כארגומנטים או מוצבות במאפיינים, ביטוי (או arrow function) הוא הבחירה הרגילה.
שמות וסגנון
שם של פונקציה הוא הבטחה לגבי מה שהיא עושה. כמה תווים נוספים בשביל שם תיאורי מחזירים את עצמם בפעם הראשונה שמישהו קורא את הקוד.
כמה מוסכמות ששווה לאמץ:
- שמות של פונקציות צריכים להיות פעלים:
fetchProfile,computeTotal,sendEmail. - השתמשו ב-
camelCase, זו הנורמה ב-JavaScript. - פונקציות שמחזירות בוליאני מתחילות לרוב ב-
is,hasאוcan:isValid,hasAccess,canEdit.
המטרה היא שמקום הקריאה ייקרא כמו משפט.
דוגמה קטנה שעובדת
מחברים את החלקים: פרמטרים, החזרה מוקדמת ושם תיאורי:
הצהרה אחת, תנאי שמירה אחד, החזרה ברורה. הצורה הזאת מכסה את רוב הפונקציות שתכתבו.
הבא בתור: Arrow Functions
הצהרות הן סוס העבודה, אבל JavaScript מודרנית נשענת מאוד על תחביר קצר יותר, arrow functions, במיוחד עבור callbacks ושורות בודדות. הן נראות אחרת, מתנהגות אחרת ביחס ל-this, והן הנושא של העמוד הבא.
שאלות נפוצות
איך מצהירים על פונקציה ב-JavaScript?
משתמשים במילת המפתח function, ואחריה שם, סוגריים לפרמטרים ובלוק. לדוגמה: function greet(name) { return 'Hi, ' + name; }. קוראים לה על ידי כתיבת השם שלה עם סוגריים: greet('Ada').
מה זה function hoisting ב-JavaScript?
הצהרות פונקציה מועברות לראש ה-scope שמכיל אותן לפני שהקוד רץ, כך שאפשר לקרוא להן בשורה שנמצאת מעל המקום שבו הן כתובות. זה חל רק על הצהרות function: ביטויי פונקציה ו-arrow functions שמוצבים ב-let או const לא עוברים hoisting באותה צורה.
מה ההבדל בין הצהרת פונקציה לביטוי פונקציה?
הצהרה עומדת בפני עצמה כפקודה (function greet() {}) ועוברת hoisting. ביטוי מציב פונקציה במשתנה (const greet = function() {}) ופועל לפי כללי ה-hoisting הרגילים של משתנים. להצהרות יש שם מעצם הגדרתן, ואילו ביטויים הם לעתים קרובות אנונימיים.