Как и другие типы данных , объект наследует свойства и методы от встроенного прототипа 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__
?