פרמטרים מול ארגומנטים
שתי מילים שמתבלבלים ביניהן כל הזמן. פרמטר הוא השם בהגדרת הפונקציה. ארגומנט הוא הערך שמעבירים בקריאה. אותו רעיון כמו ב-Python וברוב השפות האחרות:
a ו-b הם פרמטרים. 2 ו-3 הם ארגומנטים. JavaScript מקשרת אותם לפי מיקום: הארגומנט הראשון לפרמטר הראשון, וכן הלאה. ההבחנה קטנה, אבל זה אוצר המילים שהודעות שגיאה ו-MDN משתמשים בו.
JavaScript גמישה לגבי מספר הארגומנטים
בניגוד לשפות רבות, ל-JavaScript לא אכפת אם מעבירים פחות מדי או יותר מדי ארגומנטים. פרמטרים חסרים הופכים ל-undefined. פרמטרים עודפים פשוט מתעלמים מהם בשקט:
הקריאה הראשונה מדפיסה Hello, Ada undefined: last לא קיבל ערך, אז הוא undefined, ו-template literals משלבים אותו בשמחה. בלי שגיאה, בלי אזהרה. הסלחנות הזו לפעמים שימושית ולפעמים מקור לבאגים, ובדיוק בגלל זה קיימים פרמטרי ברירת מחדל.
הגדרת ערך ברירת מחדל
כתבו = וערך אחרי שם הפרמטר. אם הקורא לא מעביר את הארגומנט הזה (או מעביר undefined), ברירת המחדל נכנסת לפעולה:
שלוש הקריאות עובדות. הראשונה והשלישית מפעילות את ברירת המחדל; השנייה משתמשת בערך שהועבר. זה תחביר של ES6: לפני 2015 הייתם צריכים לכתוב name = name || "friend" בתוך הגוף, ולזה היו באגים משלו סביב ערכי falsy כמו 0 ו-"".
ברירות מחדל יכולות להיות כל ביטוי, לא רק ליטרלים:
הביטוי מחושב בכל קריאה, לא פעם אחת כשהפונקציה מוגדרת. אז אין כאן את מלכודת ברירת המחדל הניתנת לשינוי שיש ב-Python: כל קריאה מקבלת new Date() חדש.
רק undefined מפעיל את ברירת המחדל
זה הכלל שמפתיע אנשים. ברירות מחדל נכנסות לפעולה כשהארגומנט הוא undefined, לא כשהוא falsy, ו_לא_ כשהוא null:
רק הקריאה האחרונה משתמשת ב-"friend". העברה מפורשת של null אומרת "הערך הוא null", ו-JavaScript מאמינה לכם. אותו דבר למחרוזות ריקות ולאפסים: הם ערכים, לא ארגומנטים חסרים.
אם אתם רוצים להתייחס ל-null כמו לערך חסר, תצטרכו לטפל בזה בעצמכם:
האופרטור ?? (nullish coalescing) מתייחס גם ל-null וגם ל-undefined כ"חסר". עוד על זה בפרק מאוחר יותר.
ברירות מחדל יכולות להתייחס לפרמטרים קודמים
פרמטרים מחושבים משמאל לימין, כך שברירת מחדל מאוחרת יכולה להשתמש בכל פרמטר שהופיע לפניה:
קריאה עם ארגומנט אחד מייצרת קובייה. שני ארגומנטים נותנים מנסרה ריבועית. הכיוון חשוב: אי אפשר להתייחס לפרמטר שעוד לא הוצהר:
function bad(a = b, b = 1) {
return a + b;
}
bad(); // ReferenceError: Cannot access 'b' before initialization
אותם כללים כמו למשתנים שהוצהרו עם let: שימוש לפני הצהרה הוא שגיאה.
ברירות מחדל ופירוק (Destructuring)
אפשר לפרק פרמטרים ולתת להם ברירות מחדל באותו זמן. זה דפוס נפוץ לארגומנטים מסוג "אובייקט אפשרויות":
פועלות כאן שתי שכבות של ברירות מחדל. הפנימיות (role = "member", active = true) ממלאות מאפיינים חסרים. ה-= {} החיצוני מטפל במקרה שבו הקורא לא מעביר ארגומנט בכלל: בלעדיו, createUser() הייתה מנסה לפרק את undefined וזורקת שגיאה.
הדפוס נראה דחוס בהתחלה, אבל הוא נמצא בכל מקום בבסיסי קוד מודרניים של JavaScript. ברגע שהעין שלכם מזהה את { ... } = {} כ"אפשרויות עם ברירות מחדל", הוא נקרא מהר.
דילוג על ארגומנט אמצעי
ל-JavaScript אין ארגומנטים בשם בסגנון Python. כדי לדלג על פרמטר אמצעי ולהשתמש בברירת המחדל שלו, מעבירים undefined במפורש:
העברת undefined עבור prefix שומרת על ברירת המחדל. זה מכוער. אם אתם מוצאים את עצמכם כותבים undefined בקריאות לעתים קרובות, זה סימן לעבור לאובייקט אפשרויות:
עכשיו הקורא מציין בשם את מה שהוא רוצה לדרוס, והסדר לא משנה.
ברירות מחדל לא נספרות ב-length
פרט קטן שכמעט אף פעם לא חשוב אבל לפעמים מבלבל. המאפיין length של פונקציה מדווח על מספר הפרמטרים לפני הראשון שיש לו ברירת מחדל:
ספריות שבודקות פונקציות (כמו חלק מכלי הבדיקות וה-DI) משתמשות ב-length כדי לספור פרמטרים "הכרחיים". טוב לדעת שהכלל קיים; לא שווה לשנן אותו אלא אם אתם כותבים כלי מהסוג הזה.
הבא בתור: Rest ו-Spread
ברירות מחדל מטפלות במקרה שבו אתם יודעים את הפרמטרים מראש. לפעמים לא: אתם רוצים שפונקציה תקבל כל מספר של ארגומנטים, או תעביר חבילה של ארגומנטים לפונקציה אחרת. בשביל זה קיימים ...rest ואופרטור ה-spread, בעמוד הבא.
שאלות נפוצות
איך מגדירים ערך ברירת מחדל לפרמטר ב-JavaScript?
כתבו = ואת ערך ברירת המחדל אחרי שם הפרמטר בחתימת הפונקציה: function greet(name = 'friend') { ... }. אם הקורא לא מעביר ערך (או מעביר undefined), נעשה שימוש בברירת המחדל. זה תחביר של ES6 והוא עובד בכל סביבות ה-JavaScript המודרניות.
מה ההבדל בין פרמטרים לארגומנטים?
פרמטרים הם השמות בהגדרת הפונקציה: ל-function add(a, b) יש הפרמטרים a ו-b. ארגומנטים הם הערכים בפועל שמועברים בקריאה: add(2, 3) מעביר את הארגומנטים 2 ו-3. ההבחנה חשובה כשקוראים הודעות שגיאה ותיעוד.
האם פרמטר ברירת מחדל נכנס לפעולה כשמעבירים null?
לא. ברירות מחדל נכנסות לפעולה רק כשהארגומנט הוא undefined (או חסר לגמרי). העברה מפורשת של null אומרת 'אני נותן לך ערך, והערך הוא null', ולכן מדלגים על ברירת המחדל. זה מפיל אנשים שמגיעים משפות שבהן null ו-undefined הם אותו דבר.
האם ערך ברירת מחדל יכול להתייחס לפרמטר אחר?
כן. פרמטרים מחושבים משמאל לימין, כך שברירת המחדל של פרמטר מאוחר יכולה להשתמש בקודמים: function box(width, height = width). אפשר גם לקרוא לפונקציות בברירת המחדל, function log(msg, time = Date.now()), והביטוי רץ מחדש בכל קריאה.