Di truyền nguyên mẫu

Giống như các loại dữ liệu khác, đối tượng kế thừa các thuộc tính và phương thức của nguyên mẫu Object tích hợp sẵn, nghĩa là đối tượng thu được sẽ chứa cả thuộc tính mà bạn đã xác định và thuộc tính nguyên mẫu chứa các phương thức kế thừa từ nguyên mẫu:

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__()

Bạn không nên truy cập trực tiếp các thuộc tính nguyên mẫu bằng khoá thuộc tính. Như mà bạn có thể nhận thấy trong ví dụ trước, điều này được ngụ ý trong [[prototype]] hoặc ký hiệu <prototype> dùng trong trình duyệt bảng điều khiển dành cho nhà phát triển và các nguồn tài liệu về khoá thuộc tính của nguyên mẫu:

// Chrome:
let emptyObject = {};

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

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

Mặc dù tất cả trình duyệt phổ biến đều sử dụng __proto__ làm tiêu chuẩn trên thực tế, nhưng đây không phải là được chuẩn hoá chính thức và nên tránh sử dụng trong mã phát hành chính thức.

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__()

Thay vào đó, bạn có thể trực tiếp truy cập và sửa đổi [[Prototype]] của một đối tượng bằng Object.getPrototypeOf()Object.setPrototypeOf() tích hợp sẵn phương thức:

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 }

Để phân biệt giữa thuộc tính kế thừa và thuộc tính do tác giả xác định, phương thức phần sau thường được gọi là "thuộc tính riêng" của đối tượng.

Phương thức Object.hasOwn() tích hợp sẵn sẽ trả về true nếu thuộc tính được chỉ định là một thuộc tính trực tiếp của đối tượng và false nếu thuộc tính đó được kế thừa hoặc không tồn tại. Bất cứ khi nào có thể, hãy sử dụng Object.hasOwn() thay cho phương thức hasOwnProperty() kế thừa (phương thức này không hỗ trợ 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

Kiểm tra kiến thức

Tại sao bạn nên tránh sử dụng __proto__?

chứ không được chuẩn hoá.
Nhiều trình duyệt không hỗ trợ tính năng này.
Điều này sẽ gây nhầm lẫn cho các trình duy trì mã trong tương lai.