ES2020 Nullish coalescing Operator

אופרטור לוגי חדש שמשלים את האופרטור "או" - || ומאפשר לנו לעשות קביעת ערך דיפולטיבי בקלות.

השם המוזר הזה מסתיר מאחוריו פיצ'ר מאוד חשוב ואופרטור חדש ומעניין של ES2020 ותוספת חשובה לג'אווהסקריפט.

אחת מהפרקטיקות היותר נפוצות לקביעת ערך דיפולטיבי של משתנה הוא באמצעוצת האופרטור || . כך למשל:

let myVar = undefined;
let a = myVar || 'default value';
console.log('a', a);  // default value

אנחנו מכניסים ערך חדש למשתנה a. ערכו של המשתנה תלוי – אם יש לנו myVar, אז משתנה a יקבל את הערך שלו. במידה ו-myVar הוא undefined. אנו מכניסים ערך דיפולטיבי.

זה עובד גם עם null:

let myVar = null;
let a = myVar || 'default value';
console.log('a', a);  // default value

הבעיה היא שגם אם הערך הוא מחרוזת ריקה, 0 או false, אנו נקבל את אותה התנהגות כמו ב-undefined\null. למשל:

let myVar = 0;
let a = myVar || 'default value';
console.log('a', a);  // default value

או:

let myVar = '';
let a = myVar || 'default value';
console.log('a', a);  // default value

וזה יכול להיות אולטרא בעייתי. למה? כי הרבה פעמים באפליקציה שלנו, הערכים 0, false או מחרוזת ריקה הם ערכים לגיטימיים שיש להם משמעות. חישבו למשל על אובייקט משתמש שאני מקבל מהשרת ואני משתמש בחלק מהפרמטרים שלו באיזושהו רכיב. אני לא יודע אם הערכים האלו קיימים בכלל באותו אובייקט.

הנה למשל דוגמה סופר ריאליסטית (לקחתי אותה מטיוטת ההצעה של ה-TC39). הערכים שאני מקבל מאובייקט מרוחק של הגדרות המשתמש הן רלוונטיות ועדיין הוא מקבל את הגדרות ברירת המחדל! כי מבחינת ה-II ערכים לגיטימיים כמו false, 0 או מחרוזת ריקה נחשבים כמו undefined/null.


const response = {
  settings: {
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

const headerText = response.settings.headerText || 'Hello, world!'; 
const animationDuration = response.settings.animationDuration || 300; 
const showSplashScreen = response.settings.showSplashScreen || true; 

console.log('headerText', headerText); // Potentially unintended. '' is falsy, result: 'Hello, world!'
console.log('animationDuration', animationDuration); // Potentially unintended. 0 is falsy, result: 300
console.log('showSplashScreen', showSplashScreen); // Potentially unintended. false is falsy, result: true

מדוע? כיוון שהאופרטור || הוא אופרטור לוגי שמבצע הערכה של מה שהוא מקבל ומחזיר את הערכים שהם לא מתפרשים כ-false. וכפי שכל מי שמתכנת בג'אווהסקריפט יודע, 0 או false הם לגמרי false. מבחינת || גם מחרוזת ריקה או NaN זו תוצאת falsy והוא יחזיר תמיד את מה שבא אחר כך. או false.

בדיוק בשביל זה יש לנו את האופרטור Nullish coalescing. האופרטור הזה, שנראה כך: ?? – הוא אופרטור שעובד בדיוק || אבל הוא מעריך כ-false רק undefined או null. ועכשיו הבעיה נפתרה לגמרי:

const response = {
  settings: {
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

const headerText = response.settings.headerText ?? 'Hello, world!'; 
const animationDuration = response.settings.animationDuration ?? 300; 
const showSplashScreen = response.settings.showSplashScreen ?? true; 

console.log('headerText', headerText); // ''
console.log('animationDuration', animationDuration); // 0
console.log('showSplashScreen', showSplashScreen); // false

אני לא רואה שום סיבה שלא להשתמש באופרטור הזה לקביעת ברירת מחדל במקום ||. כרגע הוא לא עובד בדפדפנים (הדגש הוא על כרגע). אבל אם יש לכם בייבל, ואמור להיות לכם, אז הכל יעבוד מעולה. הנה ה-codepen שבו אפשר לבדוק את העניין:

See the Pen Nullish Coalescing by Ran Bar-Zik (@barzik-the-vuer) on CodePen.

פוסטים נוספים שכדאי לקרוא

פתרונות ומאמרים על פיתוח אינטרנט

יישום של nonce על מנת להגן מפני התקפות injection

בפוסט הקודם הסברתי על hash עם CSP על משאבי inline – שזה נחמד ומעולה אבל פחות ישים בעולם האמיתי שבו בדרך כלל התוכן ה-inline (בין

גלילה לראש העמוד