Como outros tipos de dados, uma herda propriedades e métodos de um protótipo Object integrado. o que significa que o objeto resultante contém as propriedades definidas e uma prototipagem com 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 são acessadas diretamente pela chave de propriedade. Conforme como você pode notar no exemplo anterior, isso está implícito no [[prototype]] ou <prototype> usada nos navegadores consoles para desenvolvedores e fontes 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 mais comuns usem __proto__ como o padrão real, isso não é formalmente padronizadas e deve 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 o Object.getPrototypeOf() e o Object.setPrototypeOf() integrados métodos:
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 propriedades herdadas de propriedades definidas pelo autor, o última é normalmente chamada de "propriedades próprias" do objeto.
O método Object.hasOwn() integrado vai retornar true se a propriedade especificada é uma propriedade direta do objeto e false se a propriedade é herdada ou não existe. Sempre que possível, use Object.hasOwn() em vez do método hasOwnProperty() herdado, que não é compatível com 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__?