אובייקטים

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

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

ליטרל של אובייקט הוא זוג סוגריים מסולסלים שמקיפים אפס או יותר ערך מפתח שנקראים 'מאפיינים', שיכול להכיל כל ערך של JavaScript.

{
    "myProperty" : true
}

מפתחות מאפיינים יכולים להיות כל סמל או string. כמו בהקצאת מזהה למשתנה כלשהו, המחרוזות שמשמשות כמפתחות מאפיין צריכות להיות צפויות תיאורי:

let carAttributes = {
    "color" : "red"
};

carAttributes
> Object { color: "red" }

למפתחות המאפיינים צריך להשתמש בליטרל מחרוזת יחידה (') או במירכאות כפולות ("), ולא ליטרל תבנית:

let carAttributes = {
    `keyString` : false
};
> Uncaught SyntaxError: expected property name, got template literal

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

let myObject = {
    'key' : {
        'subkey' : true,
        'othersubkey' : false
    }
};

myObject;
> Object { key: Object { subkey: true, othersubkey: false } }

כשהערך של מאפיין הוא פונקציה, המאפיין נקרא 'method'.

const myObject = {
    "myProperty" : true,
    myMethod() {
        console.log( "This is a method." );
    }
}

myObject.myProperty;
> true

myObject.myMethod();
> "This is a method."

אפשר גם ליצור אובייקט באמצעות מילת המפתח new:

let myObject = new Object();

בדוגמאות הקודמות הוקצו לליטרל האובייקטים שנוצרו לאחרונה למשתנים. זו לא חובה, כי כמו כל סוג אחר של נתונים, אפשר להשתמש אובייקט ללא מזהה בכל מקום שבו הוא צפוי. אבל, בליטרל של אובייקט צריך להוסיף סוגריים בכל הקשר שבו אפשר לבלבל אותו. להצהרה מסוג חסימה, בהינתן ששני התחביר המסולסלים דומים ({}). אתחול משתנה אף פעם לא מחייב זאת.

{ "value" : 2 }
> Uncaught SyntaxError: unexpected token: ':'

({ "value" : 2 })
> Object { value: 2 }

let valObj = { "value" : 2 };

valObj;
> Object { value: 2 }

בשונה לפרימיטיביים, אין הבדל משמעותי בתוצאות של יצירת של אובייקט באמצעות new Object() ויצירת ליטרל של אובייקט, כי ובמקרה כזה כל אחד מהמקרים יהיה אובייקט עם מאפיינים שעברו בירושה אב טיפוס של Object. אבל יש הבדל מעשי אחד בין שני הצרכים האלו תחביריים.

מילת המפתח new חייבת להגדיר אובייקט ריק שמתמלא בנתונים מאוחר יותר:

let myObject = new Object();

myObject.booleanValue = true;
myObject.stringValue = "My string.";

אפשר לאכלס ליטרל של אובייקט בנתונים לאחר יצירתו:

let myObject = {
    'booleanValue' : true,
    'stringValue' : "My string."
};

למרות שאין בו הרבה שימוש מעשי, אפשר להשתמש ב-new Object() כדי להפוך לפרימיטיבית של אובייקטים מאותו סוג, כמו אלו שמוחזרים באמצעות מילת המפתח new יחד עם ה-constructor שלה מותאמת אישית. לדוגמה, הפונקציה הבאה מקבילה לפונקציה new Number( 10 ):

let myObject = new Object( 10 );

myObject;
> Number { 10 }

הערכים null ו-undefined יוצרים אובייקט ריק, זהה מבחינה פונקציונלית כדי להפעיל את new Object() בלי לספק ארגומנט.

העברת ליטרל של אובייקט אל new Object() כארגומנט מעבירה את האובייקט מילולית מבלי לשנות אותו:

let myObject = new Object( { myValue : 10 } );

myObject;
> Object { myValue: 10 }

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

בדיקת ההבנה

באילו סוגי סימון אפשר להשתמש כדי להגדיר מאפיינים של אובייקט?

סימון נקודות
סימון סוגריים
סימון המחזור
סימון קו

איזה מהתחביר הבא הוא התחביר הנכון לקבלת הערך מתוך myProp

myObj["myProp"];
myObj{"myProp"};
myObj("myProp");