ירושה של אב טיפוס

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

let myObject = {
    'booleanValue' : true
};

myObject;
> Object { booleanValue: true }
    booleanValue: true
    [[prototype]]: Object { … }
            __defineGetter__: function __defineGetter__()
            __defineSetter__: function __defineSetter__()
            __lookupGetter__: function __lookupGetter__()
            __lookupSetter__: function __lookupSetter__()
            __proto__: …
                constructor: function Object()
                hasOwnProperty: function hasOwnProperty()
                isPrototypeOf: function isPrototypeOf()
                propertyIsEnumerable: function propertyIsEnumerable()
                toLocaleString: function toLocaleString()
                toString: function toString()
                valueOf: function valueOf()
                <get __proto__()>: function __proto__()
                <set __proto__()>: function __proto__()

מאפייני אב טיפוס לא מיועדים לגישה ישירה באמצעות מפתח מאפיין. כפי שאולי הבחנתם בדוגמה הקודמת, הוא משתמע מהסימון [[prototype]] או <prototype> שבו נעשה שימוש במסופי המפתחים של דפדפנים, ובמקורות התיעוד של מפתח המאפיין של אב הטיפוס:

// Chrome:
let emptyObject = {};

emptyObject;
> {}
  [[prototype]]: Object
// Firefox:
let emptyObject = {};

emptyObject;
> Object {  }
  <prototype>: Object { … }

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

let emptyObject = {};

emptyObject.__proto__;
> Object { … }
    __defineGetter__: function __defineGetter__()
    __defineSetter__: function __defineSetter__()
    __lookupGetter__: function __lookupGetter__()
    __lookupSetter__: function __lookupSetter__()
    __proto__:
        constructor: function Object()
        hasOwnProperty: function hasOwnProperty()
        isPrototypeOf: function isPrototypeOf()
        propertyIsEnumerable: function propertyIsEnumerable()
        toLocaleString: function toLocaleString()
        toString: function toString()
        valueOf: function valueOf()
        <get __proto__()>: function __proto__()
        <set __proto__()>: function __proto__()

במקום זאת, אפשר לגשת ל-[[Prototype]] של אובייקט ולשנות אותו ישירות באמצעות השיטות Object.getPrototypeOf() ו-Object.setPrototypeOf() המובנות:

let myObj = { "value" : 5 };
let protoParent = { "protoValue" : true };

myObj;
Object { value: 5 }
    value: 5
    <prototype>: Object { … }

Object.getPrototypeOf( myObj );
> Object { … }
    __defineGetter__: function __defineGetter__()
    __defineSetter__: function __defineSetter__()
    __lookupGetter__: function __lookupGetter__()
    __lookupSetter__: function __lookupSetter__()
    __proto__:
    constructor: function Object()
    hasOwnProperty: function hasOwnProperty()
    isPrototypeOf: function isPrototypeOf()
    propertyIsEnumerable: function propertyIsEnumerable()
    toLocaleString: function toLocaleString()
    toString: function toString()
    valueOf: function valueOf()
    <get __proto__()>: function __proto__()
    <set __proto__()>: function __proto__()

Object.setPrototypeOf( myObj, protoParent );
> Object { value: 5 }
    value: 5
    <prototype>: Object { protoValue: true }

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

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

let myObject = {
    'myValue' : 100
};

Object.hasOwn( myObject, 'myValue' );
> true

myObject.__proto__; // The Object prototype inherited by `myObject` is present:
> Object { … }

Object.hasOwn( myObject, '__proto__' ); // The Object prototype inherited by `myObject` is not an "own property:"
> false

בחינת ההבנה

למה כדאי להימנע משימוש באפליקציה __proto__?

זו לא שיטת מדידה סטנדרטית.
סוג זה אינו נתמך על ידי דפדפנים רבים.
הפעולה הזו תבלבל את המנהלים העתידיים של הקוד.