Orientação a objetos baseada em protótipos
Tags: javascript, oop, braziliandevs
Published: 2022-04-27 21:01:53

<u>Nem só de c++ like vive o homem! </u>

Todos nós conhecemos algumas linguagens orientadas a objetos do mercado. Como JAVA, C++ C# . 

Todas tem em comum que são orientada objetos utilizando CLASSES. A palavra Class.

Muitos programadores pensam, alias afirmam que orientação a obejtos é isso uso de classes. 

Alguns mais puristas preferem dizer, programação orientada a classes que por algum acaso tem objetos nelas. 

Classes abstratas, interfaces, public, protected, private entre outras coisas são coisas ligadas mais a linguagem que a orientação a objetos em si

O que queremos fazer aqui é mostrar que existe outro meio de obter orientação a objetos. 

A forma Prototipica onde sua maior expoente é o Javascript 
Javascript é uma linguagem orientada a objetos prototipica. 


"A programação baseada em protótipos é um estilo de programação orientada a objetos em que a reutilização de comportamento (conhecida como herança) é realizada por meio de um processo de reutilização de objetos existentes que servem como protótipos."

Em uma linguagem baseada em protótipo, um objeto pode conter dados e comportamento. É uma coisa auto-suficiente. Para criar um novo objeto, basta chamar o método "copy" em um objeto existente.

Em JS todo objeto tem uma propriedade chamada Prototype. 

Por: Adam Spitz
Existem várias razões psicológicas pelas quais eu(Adam Spitz) acho que os protótipos funcionam melhor, mas aqui estão algumas razões mais práticas:
As regras da linguagem podem ser mais simples. Por exemplo, você não se depara com problemas como "Uma classe é um objeto?" e "Se uma classe é um objeto, de qual classe é uma instância?" (Em Java, uma classe é meio que um objeto, mas não muito útil. Em Smalltalk, uma classe é um objeto próprio, mas por causa disso, existe um sistema de metaclasses complexo e bobo. 
Em Self, a questão apenas não aparece - você obtém todo o poder do Smalltalk, sem a complexidade extra.)
Você pode dar um comportamento especializado a objetos individuais. Isso tem todos os tipos de uso, mas é particularmente útil na depuração. Eu tenho um objeto na tela que não está se comportando corretamente, então peço para ver o código desse objeto e substituir um método ou dois (apenas nesse objeto específico) para me ajudar a depurá-lo.

Alguns ornitorrincos (como o SingletonPattern ) desaparecem completamente. Se você quer que haja apenas um de um tipo particular de objeto, então... faça apenas um deles. Se você não quiser que ele possa ser copiado, não forneça um método de "cópia".

Você começa a pensar em um monte de novos tipos de objetos que você realmente não poderia pensar em uma linguagem baseada em classes. Por exemplo, eu gosto particularmente dos objetos namespace de Self. (Self tem um sistema de namespace muito bom, sem nenhuma regra especial relacionada a namespace na linguagem - são apenas objetos comuns. O aninhamento de namespaces é feito usando herança comum.)
-- Adam Spitz

Um protótipo representa o comportamento padrão para um conceito, e novos objetos podem reutilizar parte do conhecimento armazenado no protótipo, dizendo como o novo objeto difere do protótipo. A abordagem do protótipo parece ter algumas vantagens para representar o conhecimento padrão, e modificando conceitos de forma incremental e dinâmica. A delegação é o mecanismo para implementar isso em linguagens orientadas a objetos. Como qualquer objeto pode ser usado como protótipo e qualquer mensagem pode ser encaminhada a qualquer momento, a delegação é a mais flexível e geral das duas técnicas. 

Agora vamos focar em JavaScript a linguagem orientada a objetos prototipica mais usada no mundo. 

Na época da Primeira Guerra do Navegador , os executivos da Netscape contrataram um cara esperto chamado Brendan Eich para montar uma linguagem que rodasse no navegador. Ao contrário de linguagens baseadas em classes, como C++ e Java, essa linguagem era baseada em Scheme uma linguagem funcional, mas devido a questões de marketing, Brendan teve que modificar a linguagem pra ela ser OOP, foi projetada para implementar um modelo de herança baseado em protótipo que é baseado no modelo da linguagem Self(que é oop prototipica). 
Na época com nome de LiveScript tinha que lembrar de alguma forma o Java. Linguagem super na moda. Então com as mudanças. 
Mudaram o nome para JavaScript, um tipo de irmão mais novo do JAVA. 

O OOP prototípico, que é conceitualmente diferente dos sistemas baseados em classes, havia sido inventado apenas alguns anos antes para resolver alguns problemas que o OOP baseado em classes apresentava e se encaixava muito bem com a natureza dinâmica do LiveScript.

Todos os objetos dentro do JS tem uma propriedade Prototype. 
Isso é muito importante, funciona como um copy(descrito acima)


Prototype, que é um objeto, herda do protótipo de seu pai, que herda do protótipo de seu pai e assim por diante.
Isso geralmente é chamado de cadeia de protótipos. 

Object.prototype, que está sempre no final da cadeia de protótipos (ou seja, no topo da árvore de herança de protótipos)

A coisa mais importante em JS na parte prototipal é sua herança. 

Todos os objetos JavaScript herdam propriedades e métodos de um protótipo:

Date herda de Date.prototype.
Array herda de Array.prototype.
Player herda de Player.prototype.
E todos eles herdam de Object.prototype. 

O método hasOwnProperty que a gente usa para saber se uma propriede existe em um objeto esta em Object.prototype

Se eu objeto precisa do metodo hasOwnProperty. 
O JS vai pesquisando até achar. Você não precisa criar o 
método hasOwnProperty, nem precisa extender de Object pra poder usar hasOwnProperty. Ele já esta lá. Pois todo objeto já herda de Object. 


Um filho de uma classe ES6 é outra definição de tipo que estende o pai com novas propriedades e métodos, que por sua vez podem ser instanciados em tempo de execução. Um filho de um protótipo é outra instância de objeto que delega ao pai quaisquer propriedades que não sejam implementadas no filho.

Para colocar um ponto muito bom nisso, um filho de um protótipo não é uma cópia de seu protótipo, nem é um objeto com a mesma forma que seu protótipo. O filho tem uma referência viva ao protótipo e qualquer propriedade de protótipo que não existe no filho é uma referência unidirecional a uma propriedade de mesmo nome no protótipo.

```javascript 

let papai = { foo: 'foo' }
let  filhote= { }
Object.setPrototypeOf(filhote, papai)

console.log(filhote.foo) // 'foo'

filhote.foo = 'bar'

console.log(filhote.foo) // 'bar'

console.log(papai.foo) // 'foo'

delete filhote.foo

console.log(filhote.foo) // 'foo'

papai.foo = 'baz'

console.log(filhote.foo) // 'baz'
```
No exemplo anterior, enquanto filhote.foo era undefined, ele fazia referência a papai.foo. 
Assim que definimos foo em filhote, filhote.foo tinha o valor 'bar', mas papai.foo manteve seu valor original. 
Uma vez que delete filhote.foo novamente se refere a papai.foo, o que significa que quando alteramos o valor do pai, filhote.foo refere-se ao novo valor.

Quase todos os objetos em JavaScript são instâncias Object que ficam logo abaixo null no topo de uma cadeia de protótipos.

A principal conclusão é que os protótipos não definem um type; eles são eles mesmos instancias e são mutáveis ​​em tempo de execução. 

JavaScript não tem "métodos" na forma como as linguagens baseadas em classes os definem. Em JavaScript, qualquer função pode ser adicionada a um objeto na forma de uma propriedade.

O modelo de herança prototípica é, de fato, mais poderoso que o modelo clássico. É, por exemplo, bastante trivial construir um modelo clássico em cima de um modelo prototípico.
Mas não o contrário. 

Entendemos que orientação a objetos prototipica é bem poderosa e parece ser mais simples que a orientação a class. 

Você lida realmente com objetos, não com algo que cria objetos. 
O pensamento é diferente. 

Uma pena que implementações prototipicas em sua maioria incluindo a do JS não sejam lá muito simples. 

```javascript 

 // function constructor
function Person(name, job, yearOfBirth){  
    this.name= name;
    this.job= job;
    this.yearOfBirth= yearOfBirth;
}
// adding calculateAge() method to the Prototype property
Person.prototype.calculateAge= function(){ 
    console.log('The current age is: '+(2019- this.yearOfBirth));
}
console.log(Person.prototype);
  
// creating Object Person1
let Person1= new Person('Jenni', 'clerk', 1986); 
console.log(Person1)
let Person2= new Person('Madhu', 'Developer', 1997);
console.log(Person2)
  
Person1.calculateAge();
Person2.calculateAge();
```
Para um exemplo sites não é confuso de entender. 

Mas a implementação do Js é confusa pela tentativa de emular 
com funções algo generico parecido com class, mas sem usar a palavra class. 

E depois colocar propriedades via prototype.

```javascript 
function fruits() {
        this.name = 'fruit 1';
        }

        function apple() {
        fruits.call(this);
        }

        apple.prototype = Object.create(fruits.prototype);
        const app = new apple();
        console.log(app.name);

```

você pode usar Object.create() 
É mais limpo e simples, 

A propriedade create de Object recebe parâmetros. O primeiro é obrigatório e será usado como protótipo do novo objeto. O segundo é um mapa de propriedades com as quais objeto já "nasce".

Create pode ser bastante útil se você usar alguma lógica mais complexa para criar seus objetos. Os dois trechos de código abaixo são equivalentes:

```javascript 

// forma verbosa
let foo = {};
foo.prototype = Array;
/

let bar = {nome: "john", idade: 21};

for (let propriedade in bar) {
    foo[propriedade] = bar[propriedade];
}

// forma curta
let foo = Object.create(Array, {nome: "john", idade: 21});

```
Mais limpo, mais simples e melhor. 

Object.create você pode "herdar" as propriedades de um objeto sem herdar seu protótipo, bem como fazer uma série de coisas interessantes. 
O que essa função 'create' faz é criar um novo objeto cujo protótipo é o que tiver sido passado como primeiro argumento:

```javascript 
var veiculo = {
    buzinar: function() {
        alert('Fom');
    }
};
var carro = Object.create(veiculo); // veiculo será o protótipo de carro
carro.buzinar();      

```
Lembre-se que, JS tem funções simples que retornam objetos. 
Voce pode usar dentro de uma função normal o Object.create ou não! 

```javascript  
function nameAndVeCount(){
  const name = this.name
  const vetCount = this.vetCount
  return {name,vetCount}
}
function Cat(name, breed, vetCount) {
    const cat = {name, breed, vetCount,nameAndVeCount};
    
    return Object.create(cat)
}
cat1 = Cat('Rome', 'Italy', 10);
cat2 = Cat('Paris', 'France', 20);

console.log(cat1.nameAndVeCount())

```
Esta é uma maneira de se fazer isso. 
Existem muitas outras. 
Com funções fabrica, funções normais e módulos você pode fazer tudo! 



Uma OBS: Class não é apenas açúcar sintatico em JS.  
{% embed https://webreflection.medium.com/js-classes-are-not-just-syntactic-sugar-28690fedf078 %}


{% embed https://dev.to/bhagatparwinder/classes-not-just-syntactic-sugar-1n0m %}

{% embed https://arunrajeevan.medium.com/class-is-not-just-a-syntactic-sugar-in-javascript-e0a28444263b %}

https://evertpot.com/syntactic-sugar 


fontes: 
https://262.ecma-international.org/5.1/#sec-4.2.1

https://web.media.mit.edu/~lieber/Lieberary/OOP/OOP.html#Delegation

https://dev.to/abdelrahmandeghedy/oop-in-javascript-1-constructor-and-prototypes-jio

https://alistapart.com/article/prototypal-object-oriented-programming-using-javascript

https://www.freecodecamp.org/news/an-intro-to-object-oriented-programming-in-javascript-objects-prototypes-and-classes-5d135e7361b1/

https://www.toptal.com/javascript/javascript-prototypes-scopes-and-performance-what-you-need-to-know

educative.io/blog/understanding-and-using-prototypal-inheritance-in-javascript

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

https://javascript.info/prototype-inheritance

https://www.javascripttutorial.net/javascript-prototypal-inheritance/

https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_baseada_em_prot%C3%B3tipos

https://developer.mozilla.org/en-US/docs/Glossary/Prototype-based_programming

https://stackoverflow.com/questions/186244/what-does-it-mean-that-javascript-is-a-prototype-based-language

https://www.techopedia.com/definition/30040/prototype-based-programming

https://wiki.c2.com/?PrototypeBasedProgramming

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/create

https://pt.stackoverflow.com/questions/30715/qual-a-diferen%C3%A7a-entre-object-create-ou-new-object-em-javascript

https://pt.stackoverflow.com/questions/15239/como-funcionam-prot%c3%b3tipos-em-javascript/15247#15247

https://medium.com/@parsyval/javascript-prototype-vs-class-a7015d5473b