ברירת מחדל חכמה יותר
ל-JavaScript תמיד היה קיצור לברירות מחדל: value || fallback. זה עובד ברוב המקרים, אבל יש בו באג מובנה: הוא מתייחס ל_כל_ ערך falsy כאל ערך חסר. 0, '' ו-false כולם מפעילים את ברירת המחדל, גם כשהם התשובה האמיתית.
אופרטור ה-nullish coalescing ?? מתקן את זה. הוא עובר לברירת המחדל רק עבור null או undefined:
0 ו-'' שורדים. null ו-undefined לא. זה כל האופרטור.
למה || לא מספיק
הנה הבאג הקלאסי ש-?? נועד למנוע:
המשתמש ביקש עוצמת קול 0 (שקט) וכינוי ריק. שניהם נדרסו בשקט, כי || לא יודע להבחין בין "חסר" לבין "falsy".
החליפו ל-??:
עכשיו 0 ו-'' עוברים בלי שינוי, ורק שדות שבאמת חסרים מקבלים את ברירת המחדל. כמעט תמיד זה מה שאתם רוצים.
המודל המנטלי
?? שואל שאלה אחת: האם הצד השמאלי הוא null או undefined? שום דבר אחר לא נחשב.
| הערך השמאלי | left || right מחזיר | left ?? right מחזיר |
|---|---|---|
null | right | right |
undefined | right | right |
0 | right | left (0) |
'' | right | left ('') |
false | right | left (false) |
NaN | right | left (NaN) |
| כל אובייקט | left | left |
בחרו ב-?? כשיש בנתונים שלכם ערכי falsy בעלי משמעות. בחרו ב-|| כשאתם באמת רוצים לדחות כל דבר falsy (מחרוזות ריקות, ספירות של אפס וכדומה). המקרה הזה קיים, אבל הוא נדיר יותר ממה שנהוג לחשוב.
Short-Circuit
כמו || ו-&&, גם ?? עושה short-circuit. אם הצד השמאלי אינו nullish, הצד הימני לא רץ בכלל:
expensiveDefault() רצה רק פעם אחת, עבור b. זה שימושי כשברירת המחדל שלכם היא קריאה לפונקציה, בקשת רשת או כל דבר אחר שעדיף לדלג עליו כשאין בו צורך.
השילוב עם Optional Chaining
?? ו-?. נוספו יחד ב-ES2020, והם תוכננו לעבוד כצוות. Optional chaining עובר על נתיב שאולי חסר ומחזיר undefined אם אחד השלבים חסר; nullish coalescing ממלא אז ברירת מחדל הגיונית:
בלי הצמד הזה, אותו קוד הוא שרשרת מכוערת של בדיקות && או try/catch. איתם, גישה בטוחה וברירות מחדל שפויות נכנסות בשורה אחת.
השמת Nullish: ??=
a ??= b מציב את b ב-a רק כש-a הוא null או undefined. זה אופרטור ההשמה הלוגית מסוג nullish, והוא עושה short-circuit: אם ל-a כבר יש ערך, הצד הימני לא מחושב.
שימו לב ש-verbose: false ו-retries: 0 נשמרים: ??= ממלא רק את מה שבאמת חסר. השוו ל-||=, שהיה דורס את שניהם.
קדימות וכלל הסוגריים
?? מסרב בכוונה להתערבב עם || או && בלי סוגריים. הקוד הזה זורק SyntaxError:
const x = a || b ?? c; // SyntaxError
מתכנני השפה החליטו שהקדימות עמומה מספיק כדי שיהיה שווה לחייב אתכם להבהיר. הוסיפו סוגריים והכול בסדר:
קיבוצים שונים, תשובות שונות. הסוגריים אינם קישוט: הם אומרים לקוראים העתידיים (ולמפענח) למה התכוונתם.
זה לא אותו דבר כמו פרמטר ברירת מחדל
לפרמטרי ברירת מחדל בחתימת פונקציה יש כלל משלהם: הם נכנסים לפעולה רק כשהארגומנט הוא undefined, לא null. זה הבדל עדין לעומת ??, שמתייחס לשניהם באותו אופן.
אם אתם רוצים שגם null יפעיל את ברירת המחדל, השתמשו ב-?? בתוך גוף הפונקציה:
הבחנה קטנה, וקל למעוד עליה כש-API מחזיר לכם null במשמעות "לא הוגדר ערך".
מתי לבחור ב-??
השתמשו ב-?? כאופרטור ברירת המחדל שלכם, אלא אם יש לכם סיבה מסוימת שלא לעשות זאת. הוא זה שמתאים לאופן שבו רוב הנתונים מתנהגים בפועל: 0, '' ו-false הם בדרך כלל ערכים אמיתיים ששווה לשמור, ורק נתונים שבאמת חסרים ראויים לברירת מחדל. שמרו את || למקרים שבהם אתם באמת רוצים להחליף כל ערך falsy.
הבא בתור: מחלקות
זה הכול לגבי אובייקטים ומערכים: יש לכם את הכלים לבנות מבני נתונים ולנווט בהם בבטחה. הפרק הבא עובר לארגון התנהגות: מחלקות, ירושה ומערכת ה-prototype שמתחתיהן.
שאלות נפוצות
מה זה אופרטור ה-nullish coalescing ב-JavaScript?
?? מחזיר את הצד הימני שלו רק כשהצד השמאלי הוא null או undefined. אחרת הוא מחזיר את הצד השמאלי כמו שהוא. value ?? fallback היא הדרך המקובלת לספק ברירת מחדל בלי ליפול על ערכים falsy שהם בכל זאת תקינים, כמו 0 או ''.
מה ההבדל בין ?? לבין || ב-JavaScript?
|| עובר לברירת המחדל עבור כל ערך falsy: 0, '', false, NaN, null, undefined. ?? עובר לברירת המחדל רק עבור null ו-undefined. אם 0 או מחרוזת ריקה הם ערכים לגיטימיים בנתונים שלכם, השתמשו ב-??. אם אתם באמת רוצים לדחות כל ערך falsy, || עדיין נכון.
אפשר לשלב nullish coalescing עם optional chaining?
כן, וזה צמד נפוץ. user?.settings?.theme ?? 'light' עובר על השרשרת בבטחה, מחזיר undefined אם משהו בדרך חסר, ואז מציב במקומו 'light'. שני האופרטורים נוספו יחד ב-ES2020 בדיוק כדי לתמוך בדפוס הזה.
מה עושה האופרטור ??=?
a ??= b מציב את b ב-a רק אם a הוא כרגע null או undefined. זו השמה לוגית מסוג nullish, קיצור של a = a ?? b, אבל עם short-circuit: אם ל-a כבר יש ערך, הצד הימני אפילו לא מחושב. שימושי למילוי ברירות מחדל חסרות באובייקט אפשרויות.