שתי דרכים להגיד "כלום"
ברוב השפות יש ערך אחד להיעדר. ב-JavaScript יש שניים: null ו-undefined. הם מתנהגים דומה מספיק כדי לבלבל מתחילים, ושונה מספיק כדי להפיל מפתחים מנוסים. שווה להשקיע עשר דקות כדי להבין את ההבחנה.
הגרסה הקצרה:
undefinedהוא מה ש-JavaScript נותנת לכם כשמשהו חסר.nullהוא מה ש_אתם_ כותבים כשרוצים להגיד "ריק בכוונה".
שימו לב לדפוס: כל undefined למעלה קרה כי JavaScript לא מצאה ערך. ה-null קרה כי מישהו כתב אותו.
מאיפה מגיע undefined
undefined מופיע בכמה מצבים מוגדרים, וכולם וריאציות על "אין ערך זמין":
בכל המקרים, JavaScript חיפשה ערך ולא מצאה שם כלום. undefined הוא הדרך של המנוע להגיד "בדקתי, לא היה ערך".
אפשר להציב undefined בעצמכם (let x = undefined;), אבל לא כדאי. השאירו אותו כסימן ל"JavaScript לא מצאה כלום". השתמשו ב-null כשההחלטה היא שלכם.
מאיפה מגיע null
null מופיע רק כשמישהו כתב אותו. זו כל הנקודה: הוא סימון מכוון.
ממשקי ה-DOM משתמשים ב-null הרבה: document.getElementById("missing") מחזיר null, לא undefined, כי הדפדפן אומר לכם במפורש "חיפשתי, והתשובה היא שאין אלמנט". גם JSON.parse("null") נותן null, כי ב-JSON אין undefined.
מודל החשיבה: undefined הוא היעדר ברירת המחדל, null הוא היעדר שנבחר.
המוזרות של typeof
הנה המפורסמת:
העובדה ש-typeof null מחזיר "object" היא באג משנת 1995 שאי אפשר היה לתקן בלי לשבור אתרים קיימים, ולכן הוא נשמר לתמיד. null הוא לא אובייקט: הוא טיפוס פרימיטיבי, בדיוק כמו undefined, מספרים, מחרוזות ובוליאנים. התוצאה של typeof פשוט משקרת לגביו.
ההשלכה המעשית: typeof חסר תועלת לזיהוי null. השתמשו בהשוואה ישירה:
או, לעתים קרובות יותר, בדקו את שניהם בבת אחת, כמו בסעיף הבא.
לבדוק את שניהם: האידיום == null
ברוב הזמן לא משנה לכם איזה ערך היעדר יש לכם: אתם רק רוצים לדעת אם משהו חסר לפני שמשתמשים בו. הבדיקה האידיומטית היא השוואה רופפת מול null:
value == null מחזיר true בדיוק עבור null ו-undefined ו-false עבור כל השאר, כולל 0, "" ו-false, וזה בדרך כלל מה שרוצים. זה המצב היחיד שבו מעדיפים == על פני ===. ה-linters יודעים את זה ומאפשרים את זה.
אם רוצים להיות מפורשים, value === null || value === undefined אומר בדיוק את אותו הדבר וקריא מאוד.
אופרטורי nullish: ?? ו-?.
שני אופרטורים נוספו במיוחד כדי להקל על העבודה עם null ו-undefined. שניהם מתייחסים לשני הערכים באותה צורה ולא נוגעים בשום דבר אחר.
Nullish coalescing (??) מספק ערך חלופי רק כשהצד השמאלי הוא null או undefined:
השוו ל-||, שהיה מחליף את 0 ב-3 כי 0 הוא falsy. ?? מחמיר יותר: הוא מופעל רק עבור שני ערכי ה-nullish.
Optional chaining (?.) עוצר את חישוב השרשרת ומחזיר undefined כשהוא פוגש null או undefined:
שני האופרטורים קיימים כי השאלה "האם הערך הזה nullish?" נפוצה כל כך. הם מוסברים לעומק בהמשך תוכנית הלימוד.
פרמטרים עם ברירת מחדל מופעלים רק עבור undefined
כלל עדין אבל חשוב: ערכי ברירת מחדל של פרמטרים נכנסים לפעולה רק עבור undefined, לא עבור null.
העברת null נחשבת ל"בחרתי במפורש שאין ערך" ומכובדת כמו שהיא. אם רוצים שגם null יפעיל ערך חלופי, השתמשו ב-?? בתוך הפונקציה:
ההבחנה הזו מכשילה אנשים שוב ושוב. ברירות מחדל מטפלות בארגומנטים חסרים, ו-?? מטפל בארגומנטים שהם nullish.
JSON וה-undefined החסר
ב-JSON יש null אבל אין undefined. זה מוביל להפתעות שקטות בזמן סריאליזציה:
השדה age נעלם לגמרי: JSON.stringify משמיט מאפיינים שהערך שלהם הוא undefined. null שורד כי JSON תומך בו. העברה של אובייקט הלוך וחזור דרך JSON היא דרך נפוצה שבה מאפייני undefined נעלמים בשקט.
במערכים, undefined הופך ל-null:
אם אתם מתכננים payload של API, העדיפו null על פני undefined לשדות "אין ערך". הוא שורד את הדרך.
מתי להשתמש בכל אחד
מוסכמה סבירה לקוד שלכם:
- תנו ל-
undefinedלסמן "לא סופק": ארגומנטים חסרים, משתנים שלא הוצבו, מאפיינים שלא קיימים. אל תציבוundefinedידנית. - השתמשו ב-
nullכשרוצים לומר במפורש "זה ריק בכוונה": משתמש שהתנתק, אפשרות שלא נבחרה, שדה טופס שנוקה. - קבלו את שניהם בגבולות ה-API (עם
== nullאו??), אבל היו עקביים לגבי מה שאתם מייצרים.
חלק ממדריכי הסגנון (כולל של TypeScript) מוותרים על null לגמרי ומשתמשים רק ב-undefined. זו גישה שאפשר להצדיק: ערך אחד פשוט יותר משניים. בחרו כלל לכל פרויקט ויישמו אותו בכל מקום.
הבא בתור: המרת טיפוסים
null ו-undefined מתנהגים בדרכים מוגדרות כש-JavaScript ממירה אותם למספרים, מחרוזות או בוליאנים: Number(null) הוא 0, אבל Number(undefined) הוא NaN, וחוסר סימטריה כזה גורם לבאגים אמיתיים. המרת טיפוסים היא הנושא הבא, וברגע שרואים את הכללים המלאים, הרבה מהמוזרויות של JavaScript מפסיקות להיות מסתוריות.
שאלות נפוצות
מה ההבדל בין null ל-undefined ב-JavaScript?
undefined אומר שעוד לא הוקצה ערך: זה מה ש-JavaScript מחזירה עבור משתנים חסרים, ארגומנטים חסרים או מאפיינים חסרים של אובייקט. null הוא 'אין כאן ערך' מפורש שאתם מציבים בכוונה. JavaScript אף פעם לא מייצרת null בעצמה, צריך לכתוב אותו.
איך בודקים גם null וגם undefined בבת אחת?
השתמשו ב-value == null. השוואה רופפת מתייחסת ל-null ול-undefined כשווים זה לזה ולא לשום דבר אחר, כך ש-x == null מחזיר true בדיוק עבור שני הערכים האלה. זה המקום היחיד שבו == במקום === הוא אידיומטי ובטוח.
למה typeof null מחזיר 'object'?
זה באג מהגרסה הראשונה של JavaScript שאי אפשר לתקן בלי לשבור את האינטרנט. typeof null מחזיר 'object' למרות ש-null הוא טיפוס פרימיטיבי. כדי לבדוק null באופן ספציפי, השוו ישירות: value === null.
האם להשתמש ב-null או ב-undefined בקוד שלי?
תנו ל-undefined לסמן 'לא סופק כלום', והשתמשו ב-null כשרוצים לאותת במפורש 'זה ריק בכוונה'. הרבה בסיסי קוד (ומדריך הסגנון של TypeScript) נמנעים מ-null לגמרי ומשתמשים רק ב-undefined. בחרו מוסכמה אחת לכל פרויקט והיצמדו אליה.