• בלוג
  • טיפ JavaScript: שדה אופציונאלי באוביקט

טיפ JavaScript: שדה אופציונאלי באוביקט

27/08/2021

כתיב האוביקטים של JavaScript קיבל המון שיפורים באזור גירסת ES6, כולל זה שמאפשר לנו להגדיר בצורה דינמית שם של מפתח:

const key = 'name';

const data = {
    [key]: 'bob'
};

שמחזיר את האוביקט עם המפתח name ובו הערך bob.

ורק עם זה אפשר להיות מאוד יצירתיים ולהפוך מערך לאוביקט עם קוד כזה:

const words = ['one', 'two', 'three'];
const wordsObject = words.map(w => ({ [w]: true })).reduce((a, b) => ({ ...a, ...b }));

// now wordsObject = { one: true, two: true, three: true }

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

const s1 = getStatus(task1);
// returns { status: 'PROCESSING' }

const s2 = getStatus(task2);
// returns { status: 'DONE', result: 8 }

אז כן אני יודע שאפשר לכתוב if בתוך הפונקציה או לבנות את האוביקט צעד אחר צעד, אבל הנה עוד טריק נחמד למי שאוהב לחסוך בפקודות:

function getStatus(task) {
    return {
        status: task.status,
        ...(task.status === 'DONE' && { result: task.result }),
    };
}

כתיב השלוש נקודות מפרק את האוביקט שהוא מקבל בסוגריים וכך אנחנו מקבלים הזדמנות להריץ קוד "בתוך" אוביקט התוצאה כדי להחליט איזה שדות יהיו בו. הפעלות לדוגמה של הפונקציה:

// prints: { status: 'PROCESSING' }
console.log(getStatus({ status: 'PROCESSING', result: 7 }));

// prints: { status: 'DONE', result: 7 }
console.log(getStatus({ status: 'DONE', result: 7 }));