Herança de prototipagem
Como outros tipos de dados, um
objeto herda propriedades e métodos de um protótipo Object
integrado,
ou seja, o objeto resultante contém as propriedades definidas e uma
propriedade de protótipo que contém os métodos herdados do protótipo:
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__()
As propriedades do protótipo não podem ser acessadas diretamente pela chave de propriedade. Como
você pode notar no exemplo anterior, isso está implícito pela notação [[prototype]]
ou <prototype>
usada nos consoles para desenvolvedores dos navegadores e nas fontes de
documentação da chave de propriedade do protótipo:
// Chrome:
let emptyObject = {};
emptyObject;
> {}
[[prototype]]: Object
// Firefox:
let emptyObject = {};
emptyObject;
> Object { }
<prototype>: Object { … }
Embora todos os navegadores comuns usem __proto__
como um padrão real, isso não é padronizado formalmente e precisa ser evitado no código de produção.
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__()
Em vez disso, é possível acessar e modificar diretamente o [[Prototype]]
de um objeto
usando os métodos integrados Object.getPrototypeOf()
e
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 }
Para diferenciar entre propriedades herdadas e definidas pelo autor, a última é normalmente chamada de "propriedades próprias do objeto".
O método Object.hasOwn()
integrado vai retornar true
se a propriedade especificada
for uma propriedade direta do objeto, e false
se ela for herdada ou
não existir. Sempre que possível, use Object.hasOwn()
em vez do método hasOwnProperty()
herdado, que não tem suporte para
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
Teste seu conhecimento
Por que evitar o uso de __proto__
?