原型繼承

如同其他資料類型, 物件繼承內建 Object 原型的屬性和方法, 這表示產生的物件會包含您定義的屬性和 prototype 屬性,其中含有繼承自原型的方法:

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__

這個指標並未標準化。
許多瀏覽器都不支援這個標記。
這樣可能會讓日後程式碼維護人員混淆。