Esqueça todo o conhecimento orientado a objetos que você aprendeu antes. Apenas considere a situação de corrida aqui. Sim, está correndo.
Recentemente, estou assistindo 24 horas de Le Mans, um evento popular na França. O carro mais rápido é chamado de protótipo de Le Mans. Embora esses carros sejam fabricados por fabricantes como "Audi" ou "Peugeot", eles não são o tipo de carros que você vê na rua ou na estrada. Eles são feitos especificamente para eventos de resistência de alta velocidade.
O fabricante investe enormes quantias de dinheiro para desenvolver, projetar e fabricar esses carros de protótipo, e os engenheiros sempre tentam tornar esse projeto ao extremo. Eles conduziram vários experimentos sobre ligas, biocombustíveis, tecnologia de frenagem, composição composta e características de segurança dos pneus. Com o tempo, algumas das técnicas nessas experiências foram melhoradas repetidamente e entraram na linha de veículos principais de produtos. Algumas das tecnologias no veículo que você está dirigindo podem ter sido estreadas no protótipo de corrida.
Você também pode dizer que esses veículos convencionais herdam os protótipos técnicos dos carros de corrida.
Até agora, temos a base para discutir os problemas de protótipo e herança no JavaScript. Embora não seja tão bom quanto o padrão de herança clássica que você conhece em C ++, Java ou C#, é tão poderoso e potencialmente mais flexível.
O JavaScript está cheio de objetos, que se refere a objetos no sentido tradicional, ou seja, "uma única entidade que contém estado e comportamento". Por exemplo, uma matriz no JavaScript é um objeto que contém vários valores e contém métodos push, reverso e pop.
var myarray = [1, 2]; myArray.push (3); myArray.Reverse (); myarray.pop (); var comprimento = myArray.length;
Agora a pergunta é: de onde vem o empurrão? As linguagens estáticas que mencionamos anteriormente "Sintaxe da classe" para definir a estrutura dos objetos, mas o JavaScript é um idioma sem "sintaxe da classe" e não pode definir cada objeto de matriz usando a sintaxe da matriz "classe". E como o JavaScript é uma linguagem dinâmica, podemos colocar métodos em objetos como realmente precisamos deles. Por exemplo, o código a seguir define um objeto Point usado para representar um ponto no espaço bidimensional e também define um método Add.
var point = {x: 10, y: 5, add: function (outro ponto) {this.x += otherpoint.x; this.y += otherpoint.y; }};No entanto, as práticas acima não são muito escaláveis. Precisamos garantir que cada objeto de ponto contenha um método Add, e também queremos que todos os objetos de ponto compartilhem a implementação do mesmo método Add, em vez de adicionar manualmente esse método a cada objeto de ponto. É aqui que o protótipo entra em jogo.
No JavaScript, cada objeto permanece oculto - uma referência a outro objeto, também conhecido como protótipo. A matriz que criamos antes de referir um objeto de protótipo, assim como os objetos de ponto que criamos nós mesmos. Como mencionado acima, as referências de protótipo estão ocultas, mas também existem implementações do ECMAScript (o nome oficial do JavaScript) que podem acessar essa referência de protótipo através do atributo __proto__ de um objeto (como o Google Chrome). Conceitualmente, podemos tratar os objetos como relacionamentos semelhantes aos representados na Figura 1-prototipo.
Figura 1
Olhando para o futuro, os desenvolvedores poderão usar a função Object.GetProTypeOf em vez do atributo __proto__ para obter referências ao protótipo de objeto. No momento da redação deste artigo, a função Object.GetProTypeOf já pode ser usada nos navegadores Google Chrome, Firefox e IE9. Mais navegadores implementarão esse recurso no futuro, porque ele já faz parte do padrão ECMAScript. Podemos usar o código a seguir para provar que os objetos MyArray e Dot que criamos se referem a dois objetos de protótipo diferentes.
Para o restante deste artigo, usarei as funções __proto__ e object.getPrototypof, principalmente porque __proto__ é mais fácil de identificar em gráficos e frases. Deve -se lembrar que ele (__proto__) não é o padrão e a função Object.GetProTypeOf é o método recomendado para visualizar protótipos de objeto.
O que torna o protótipo tão especial?
Não respondemos a esta pergunta: de onde vem o empurrão em uma matriz? A resposta é: vem do objeto MyArray Prototype. A Figura 2 é uma captura de tela do depurador de scripts no Chrome. Chamamos o objeto.GetProTypeOf Method para visualizar o objeto de protótipo de MyArray.
Figura 2
Observe que existem muitos métodos no objeto de protótipo de MyArray, incluindo os chamados métodos Push, Pop e Reverse em exemplos de código. Portanto, o método push inclui o objeto de protótipo, mas como o método MyArray se refere a ele?
MyArray.push (3);
O primeiro passo para entender como funciona é perceber que o protótipo não é especial. O protótipo é apenas um objeto normal. Você pode adicionar métodos, propriedades ao protótipo e tratá -los como outros objetos JavaScript. No entanto, para aplicar a declaração de "porco" no romance de George Orwell, "Animal Farm" - todos os objetos devem ser iguais, mas alguns objetos (aqueles que seguem as regras) são mais iguais que outros.
Os objetos de protótipo no JavaScript são realmente especiais porque seguem as seguintes regras. Quando dizemos ao JavaScript que queremos chamar o método de push de um objeto ou ler a propriedade X do objeto, o tempo de execução procurará primeiro o próprio objeto. Se o tempo de execução não conseguir encontrar o que deseja, segue a referência __proto__ e o protótipo de objeto para procurar o membro. Quando chamamos o método de push de MyArray, o JavaScript não encontra o método push no objeto MyArray, mas no objeto de protótipo de MyArray, então o JavaScript chama esse método (veja a Figura 3).
Figura 3
O comportamento descrito acima refere -se a um objeto herdando qualquer método ou propriedade no protótipo. No JavaScript, a herança é realmente alcançada sem usar a sintaxe da classe. Assim como um carro que herda a tecnologia correspondente de um protótipo de corrida, um objeto JavaScript também pode herdar recursos funcionais de um objeto de protótipo.
A Figura 3 também mostra que cada objeto de matriz também pode manter seu próprio estado e membros. Ao solicitar o atributo de comprimento de MyArray, o JavaScript obterá o valor do atributo de comprimento em MyArray sem ler o valor correspondente no protótipo. Podemos "substituir" o método push adicionando um método como push ao objeto. Isso ocultará efetivamente a implementação do método push no protótipo.
A verdadeira magia dos protótipos no JavaScript é como vários objetos mantêm referências ao mesmo objeto de protótipo. Por exemplo, se criarmos duas matrizes como esta:
var myarray = [1, 2]; var youRArray = [4, 5, 6];
Em seguida, essas duas matrizes compartilharão o mesmo objeto de protótipo, e o código a seguir avaliará para true:
Object.getPrototypeOf (MyArray) === Object.getPrototypeOf (yourArray);
Se nos referirmos ao método push em dois objetos de matriz, o JavaScript procurará o método push compartilhado no protótipo.
Figura 4
Os objetos de protótipo no JavaScript fornecem funções de herança e, ao mesmo tempo, o compartilhamento desse método é implementado. O protótipo também é encadeado. Em outras palavras, como um objeto de protótipo é apenas um objeto, um objeto de protótipo pode ser mantido em uma referência a outro objeto de protótipo. Se você revisitar a Figura 2, poderá ver que a propriedade __proto__ do protótipo é um valor não nulo que aponta para outro protótipo. Quando o JavaScript procura membros como o método push, ele verifica cada objeto ao longo da cadeia de referência do protótipo até que seja encontrado ou chegue ao final da cadeia de protótipo. As cadeias de protótipo abrem um caminho flexível para herança e compartilhamento.
A próxima pergunta que você pode fazer é: como configuro referências de protótipo a esses objetos personalizados? Por exemplo, o objeto Point usado anteriormente, como posso adicionar o método ADD ao objeto Prototype e herdar o método de vários objetos de ponto? Antes de responder a essa pergunta, precisamos olhar para as funções.
As funções no JavaScript também são objetos. Essa declaração traz vários resultados importantes, e não abordaremos todos os assuntos neste artigo. Entre eles, a capacidade de atribuir uma função a uma variável e passar uma função como um parâmetro para outra função constitui o paradigma básico da expressão moderna de programação de JavaScript.
O que precisamos prestar atenção é que a função em si é um objeto; portanto, a função pode ter seus próprios métodos, propriedades e referenciar um objeto de protótipo. Vamos discutir o significado do código a seguir.
// Isso retornará true: typeof (array) === "function" // Essa expressão também é: object.getProTypeOf (Array) === Object.getPrototypeOf (function () {}) // Essa expressão é a mesma: Array.protype! = NULLA primeira linha do código prova que a matriz em JavaScript é uma função. Veremos como chamar a função da matriz para criar um novo objeto de matriz. A próxima linha de código prova que o objeto Array usa o mesmo protótipo que qualquer outro objeto de função, assim como vemos que o mesmo protótipo é compartilhado entre objetos de matriz. A última linha de código prova que a função da matriz possui uma propriedade de protótipo, e esse protótipo de propriedade aponta para um objeto válido. Esta propriedade do protótipo é muito importante.
Cada objeto de função no JavaScript possui uma propriedade de protótipo. Nunca confunda o atributo __proto__ desta propriedade do protótipo. Eles têm um propósito diferente, nem apontam para o mesmo objeto.
// return trueObject.getPrototypeof (array)! = Array.prototype
Array .__ Proto__ fornece um protótipo de matriz. Trate -o como um objeto herdado pela função da matriz.
Array.protoype fornece objetos de protótipo para todas as matrizes. Ou seja, ele fornece objetos de protótipo de objetos de matriz como MyArray e também contém métodos que todas as matrizes herdarão. Podemos escrever algum código para provar esse fato.
// truearray.prototype == object.getPrototypeof (myArray) // também é truearray.prototype == object.getPrototypeOf (yourArray);
Também podemos usar esse novo conhecimento para repintar o diagrama anterior.
Figura 5
Com base no que você sabe, imagine o processo de criar um novo objeto e fazer o novo objeto se comportar como uma matriz. Uma maneira é usar o seguinte código.
// Crie um novo objeto vazio var o = {}; // herdado do mesmo protótipo, um objeto de matriz o .__ proto__ = array.prototype; // agora podemos chamar qualquer método da matriz ... o.push (3);Embora esse código seja interessante e funcione, o problema é que nem todo ambiente JavaScript suporta propriedades de objeto __proto__ escritas. Felizmente, o JavaScript possui um mecanismo padrão para criar objetos. Requer apenas um operador para criar novos objetos e definir a referência __proto__ do novo objeto, que é o operador "novo".
var o = new Array (); O.push (3);
O novo operador do JavaScript possui três tarefas básicas. Primeiro, ele cria um novo objeto vazio. Em seguida, ele definirá a propriedade __proto__ do novo objeto para corresponder às propriedades do protótipo da função chamada. Finalmente, o operador chama a função, passando o novo objeto como uma referência "essa". Se você deseja estender as duas últimas linhas de código, ele se tornará a seguinte situação:
var o = {}; o .__ proto__ = array.prototype; array.call (o); o.push (3);O método de chamada da função permite especificar o objeto referenciado por "this" dentro da função ao chamar a função. Obviamente, o autor da função precisa implementar essa função neste caso. Uma vez que o autor cria tal função, ele pode ser chamado de construtor.
Construtor
Os construtores são os mesmos que as funções comuns, mas têm as duas propriedades especiais a seguir.
Array é um exemplo de construtor. A função da matriz precisa ser usada com o novo operador e a letra de matriz inicial é capitalizada. O JavaScript inclui a matriz como uma função interna, e qualquer pessoa pode escrever seu próprio construtor. De fato, podemos finalmente escrever um construtor para os objetos de pontos criados anteriormente.
var point = function (x, y) {this.x = x; this.y = y; this.add = function (outro ponto) {this.x += otherpoint.x; this.y += otherpoint.y; }} var p1 = novo ponto (3, 4); var p2 = novo ponto (8, 6); p1.Add (p2);No código acima, usamos o novo operador e a função de ponto para construir um objeto Point, que possui os atributos X e Y e um método Add. Você pode imaginar o resultado final, conforme mostrado na Figura 6.
Figura 6
O problema agora é que ainda existe um método de adição separado em cada um de nossos objetos pontos. Usando o protótipo e a herança que aprendemos, preferimos transferir o método ADD do objeto Point de cada instância do ponto para o ponto.Prototype. Para alcançar o efeito de herdar o método ADD, tudo o que precisamos fazer é modificar o objeto Point.Prototype.
var point = function (x, y) {this.x = x; this.y = y;} Point.prototype.add = function (Otherpoint) {this.x += otherpoint.x; this.y += otherpoint.y;} var p1 = novo ponto (3, 4); var p2 = novo ponto (8, 6); p1.add (p2);A missão está feita! Acabamos de concluir o modo de herança do protótipo em JavaScript!
Figura 7
Resumir
Espero que este artigo o ajude a descobrir o mistério dos conceitos de protótipo JavaScript. O que vi a princípio foi como o protótipo permitiu que um objeto herdasse funções de outros objetos e depois vi como combinar o novo operador e construtor para construir o objeto. O que é mencionado aqui é apenas o primeiro passo para desbloquear o poder e a flexibilidade do protótipo de objeto. Este artigo incentiva você a descobrir e aprender novas informações sobre protótipos e idiomas JavaScript para si mesmo.
Além disso, dirija com cuidado. Você nunca saberá o que a tecnologia (falha) que esses veículos que viajam na estrada herdarão de seus protótipos.
Link original: Script Junkie Tradução: Bole Online - Emje