Protótipo JavaScript

Resumo : neste tutorial, você aprenderá sobre o protótipo JavaScript e como ele funciona nos bastidores.

Introdução ao protótipo JavaScript

Em JavaScript, os objetos podem herdar recursos uns dos outros por meio de protótipos . Cada objeto tem sua própria propriedade chamada a prototype.

Como o prototypepróprio também é outro objeto, o prototypetem o seu próprio prototype. Isso cria algo chamado cadeia de protótipos . A cadeia de protótipos termina quando um protótipo tem nullseu próprio protótipo.

Suponha que você tenha um objeto personcom uma propriedade chamada name:

let person = {'name' : 'John'}Linguagem de código:  JavaScript  ( javascript )

Ao examinar o personobjeto no console, você descobrirá que o personobjeto tem uma propriedade chamada prototypeindicada por [[Prototype]]:

O próprio protótipo é um objeto com propriedades próprias:

Quando você acessa uma propriedade de um objeto, se o objeto tiver essa propriedade, ele retornará o valor da propriedade. O exemplo a seguir acessa a namepropriedade do personobjeto:

Ele retorna o valor da namepropriedade conforme o esperado.

Porém, se você acessar uma propriedade que não existe em um objeto, o mecanismo JavaScript irá pesquisar no protótipo do objeto.

Se o mecanismo JavaScript não conseguir encontrar a propriedade no protótipo do objeto, ele pesquisará no protótipo do protótipo até encontrar a propriedade ou chegar ao final da cadeia de protótipos.

Por exemplo, você pode chamar o toString()método do personobjeto assim:

O toString()método retorna a representação em string do personobjeto. Por padrão, é o [object Object]que não é óbvio.

Observe que quando uma função é um valor da propriedade de um objeto, ela é chamada de método . Portanto, um método é uma propriedade com valor como função.

Neste exemplo, quando chamamos o toString()método no personobjeto, o mecanismo JavaScript o encontra no personobjeto.

Como o personobjeto não possui o toString()método, ele procurará o toString()método no objeto protótipo da pessoa.

Como o protótipo da pessoa possui o toString()método, o JavaScript chama o toString()objeto protótipo da pessoa.

Ilustração do protótipo JavaScript

JavaScript tem a função integrada Object(). O typeofoperador retorna 'function'se você passar a Objectfunção para ele. Por exemplo:

typeof(Object)Linguagem de código:  JavaScript  ( javascript )

Saída:

'function'Linguagem de código:  JavaScript  ( javascript )

Observe que Object()é uma função, não um objeto. É confuso se esta é a primeira vez que você aprende sobre o protótipo JavaScript.

Além disso, JavaScript fornece um objeto anônimo que pode ser referenciado através da prototypepropriedade da Object()função:

console.log(Object.prototype);Linguagem de código:  JavaScript  ( javascript )

O Object.prototypeobjeto possui algumas propriedades e métodos úteis , como toString()e valueOf().

O Object.prototypetambém possui uma propriedade importante chamada constructorque faz referência à Object()função.

A instrução a seguir confirma que a Object.prototype.constructorpropriedade faz referência à Objectfunção:

console.log(Object.prototype.constructor === Object); // trueLinguagem de código:  JavaScript  ( javascript )

Suponha que um círculo represente uma função e um quadrado represente um objeto. A imagem a seguir ilustra a relação entre a Object()função e o Object.prototypeobjeto:

Protótipo JavaScript

Primeiro, defina uma função construtora chamada Personda seguinte forma:

function Person(name) {
    this.name = name;
}Linguagem de código:  JavaScript  ( javascript )

Neste exemplo, a Person()função aceita um nameargumento e o atribui à namepropriedade do thisobjeto.

Nos bastidores, o JavaScript cria uma nova função Person()e um objeto anônimo:

Protótipo JS - Tipo de pessoa

Assim como a Object()função, a Person()função possui uma propriedade chamada prototypeque faz referência a um objeto anônimo. O objeto anônimo possui a constructorpropriedade que faz referência à Person()função.

O seguinte mostra a Person()função e o objeto anônimo referenciado por Person.prototype:

console.log(Person);
console.log(Person.prototype);Linguagem de código:  CSS  ( css )

Além disso, o JavaScript vincula o Person.prototypeobjeto ao Object.prototypeobjeto por meio do [[Prototype]], que é conhecido como ligação de protótipo .

A ligação do protótipo é indicada [[Prototype]]na figura a seguir:

Protótipo JS - Protótipo de pessoa

Definindo métodos no objeto protótipo JavaScript

O seguinte define um novo método chamado greet()no Person.prototypeobjeto:

Person.prototype.greet = function() {
    return "Hi, I'm " + this.name + "!";
}Linguagem de código:  JavaScript  ( javascript )

Neste caso, o mecanismo JavaScript adiciona o greet()método ao Person.prototypeobjeto:

O seguinte cria uma nova instância do Person:

let p1 = new Person('John');Linguagem de código:  JavaScript  ( javascript )

Internamente, o mecanismo JavaScript cria um novo objeto nomeado p1 e vincula o p1objeto ao Person.prototypeobjeto por meio da ligação de protótipo:

O elo entre p1, Person.prototypee Object.protoypeé chamado de cadeia de protótipos .

O seguinte chama o greet()método no p1objeto:

let greeting = p1.greet();
console.log(greeting);Linguagem de código:  JavaScript  ( javascript )

Como p1não possui o greet()método, o JavaScript segue a ligação do protótipo e o encontra no Person.prototypeobjeto.

Como o JavaScript pode encontrar o greet()método no Person.prototypeobjeto, ele executa o greet()método e retorna o resultado:

O seguinte chama o toString()método no p1objeto:

let s = p1.toString();
console.log(s);Linguagem de código:  JavaScript  ( javascript )

Nesse caso, o mecanismo JavaScript segue a cadeia de protótipos para procurar o toString()método no arquivo Person.prototype.

Como Person.prototypenão possui o toString()método, o mecanismo JavaScript vai até a cadeia de protótipos e procura o toString()método no Object.prototypeobjeto.

Como o JavaScript pode encontrar o toString()método no arquivo Object.prototype, ele executa o toString()método.

Se você chamar um método que não existe no objeto Person.prototypeand Object.prototype, o mecanismo JavaScript seguirá a cadeia de protótipos e gerará um erro se não conseguir encontrar o método. Por exemplo:

p1.fly();
Linguagem de código:  CSS  ( css )

Como o fly()método não existe em nenhum objeto da cadeia de protótipos, o mecanismo JavaScript emite o seguinte erro:

TypeError: p1.fly is not a functionLinguagem de código:  JavaScript  ( javascript )

O seguinte cria outra instância cuja Personpropriedade name é 'Jane':

let p2 = new Person('Jane');Linguagem de código:  JavaScript  ( javascript )
Protótipo JS - objetos de duas pessoas

O p2objeto possui as mesmas propriedades e métodos que o p1objeto.

Concluindo, quando você define um método no prototypeobjeto, esse método é compartilhado por todas as instâncias.

Definindo métodos em um objeto individual

O seguinte define o draw()método no p2objeto.

p2.draw = function () {
    return "I can draw.";
};
Linguagem de código:  JavaScript  ( javascript )

O mecanismo JavaScript adiciona o draw()método ao p2objeto, não ao Person.prototypeobjeto:

Protótipo JS - objeto com método

Isso significa que você pode chamar o draw()método no p2objeto:

p2.draw();Linguagem de código:  CSS  ( css )

Mas você não pode chamar o draw()método no p1objeto:

p1.draw()Linguagem de código:  CSS  ( css )

Erro:

TypeError: p1.draw is not a functionLinguagem de código:  JavaScript  ( javascript )

Quando você define um método em um objeto, o método fica disponível apenas para esse objeto. Não pode ser compartilhado com outros objetos por padrão.

Obtendo ligação de protótipo

O __proto__é pronunciado como dunder proto. The __proto__é uma propriedade de acesso do Object.prototypeobjeto. Ele expõe a ligação do protótipo interno ( [[Prototype]])de um objeto através do qual ele é acessado.

O __proto__ foi padronizado no ES6 para garantir compatibilidade com navegadores da web. No entanto, pode ser descontinuado em favor de Object.getPrototypeOf()no futuro. Portanto, você nunca deve usar o __proto__ em seu código de produção.

p1.__proto__expõe o [[Prototype]]que faz referência ao Person.prototypeobjeto.

Da mesma forma, p2.__proto__também faz referência ao mesmo objeto quep1.__proto__:

console.log(p1.__proto__ === Person.prototype); // true
console.log(p1.__proto__ === p2.__proto__); // trueLinguagem de código:  JavaScript  ( javascript )

Conforme mencionado anteriormente, você deve usar o Object.getPrototypeOf()método em vez do __proto__. O Object.getPrototypeOf()método retorna o protótipo de um objeto especificado.

console.log(p1.__proto__ === Object.getPrototypeOf(p1)); // trueLinguagem de código:  JavaScript  ( javascript )

Outra forma popular de obter a ligação do protótipo é quando o Object.getPrototypeOf()método não está disponível por meio da constructorpropriedade como segue:

p1.constructor.prototypeLinguagem de código:  CSS  ( css )

O p1.constructorreturn Person, portanto, p1.constructor.prototyperetorna o objeto protótipo.

Sombreamento

Veja a seguinte chamada de método:

console.log(p1.greet());Linguagem de código:  CSS  ( css )

O p1objeto não possui o greet()método definido, portanto o JavaScript sobe até a cadeia de protótipos para encontrá-lo. Neste caso, ele pode encontrar o método no Person.prototypeobjeto.

Vamos adicionar um novo método ao objeto p1com o mesmo nome do método no Person.prototypeobjeto:

p1.greet = function() {
    console.log('Hello');
}Linguagem de código:  JavaScript  ( javascript )

E chame o greet()método:

console.log(p1.greet());Linguagem de código:  CSS  ( css )

Como o p1objeto possui o greet()método, o JavaScript apenas o executa imediatamente, sem procurá-lo na cadeia de protótipos.

Este é um exemplo de sombreamento. O greet()método do p1objeto obscurece o greet()método do prototypeobjeto ao qual o p1objeto faz referência.

Resumo

  • A Object()função possui uma propriedade chamada prototypeque faz referência a um Object.prototypeobjeto.
  • O Object.prototypeobjeto possui todas as propriedades e métodos que estão disponíveis em todos os objetos, como toString()e valueOf().
  • O Object.prototypeobjeto possui a constructorpropriedade que faz referência à Objectfunção.
  • Toda função possui um prototypeobjeto. Este objeto protótipo faz referência ao Object.prototypeobjeto por meio [[prototype]]de ligação ou __proto__propriedade.
  • A cadeia de protótipos permite que um objeto use os métodos e propriedades de seus prototypeobjetos por meio de [[prototype]]ligações.
  • O Object.getPrototypeOf()método retorna o objeto protótipo de um determinado objeto. Use o Object.getPrototypeOf()método em vez de __proto__.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *