A primeira diferença pode ser resumida como: thisrefere-se à Instância da classe. prototyperefere-se à definição .
Digamos que temos a seguinte classe:
var Flight = function ( number ) { this.number = number; };
Então, aqui estamos nos anexando this.numbera todas as instâncias da classe, e faz sentido, porque todas Flightdevem ter seu próprio número de voo.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
Por outro lado, prototypedefine uma única propriedade que pode ser acessada por todas as instâncias.
Agora, se quisermos obter o número do voo, podemos simplesmente escrever o seguinte trecho e todas as nossas instâncias receberão uma referência a esse objeto recém-protegido.
Flight.prototype.getNumber = function () { return this.number; };
A segunda diferença é sobre a maneira como o JavaScript procura uma propriedade de um objeto. Quando você está procurando Object.whatever, o JavaScript vai até o objeto Objeto principal (o objeto que todo o resto herdou) e, assim que encontrar uma correspondência, ele retornará ou o chamará.
Mas isso só acontece para as propriedades prototipadas. Portanto, se você tiver algum lugar nas camadas mais altas this.whatever, o JavaScript não o considerará uma correspondência e continuará a pesquisa.
Vamos ver como isso acontece na realidade.
Primeira nota que [quase] tudo são objetos em JavaScript. Tente o seguinte:
typeof null
Agora vamos ver o que está dentro de um Object(observe Maiúsculas Oe .no final). Nas Ferramentas do desenvolvedor do Google Chrome, quando você digita, .você obterá uma lista de propriedades disponíveis dentro desse objeto específico.
Object.
Agora faça o mesmo para Function:
Function.
Você pode perceber o namemétodo. Vá em frente e vamos ver o que acontece:
Object.name
Function.name
Agora vamos criar uma função:
var myFunc = function () {};
E vamos ver se temos o namemétodo aqui também:
myFunc.name
Você deve ter uma string vazia, mas tudo bem. Você não deve receber um erro ou exceção.
Agora, vamos adicionar algo a esse deus Objecte ver se o encontramos em outros lugares também?
Object.prototype.test = "Okay!";
E lá vai você:
Object.prototype.test
Function.prototype.test
myFunc.prototype.test
Em todos os casos, você deve ver "Okay!".
Com relação aos prós e contras de cada método, você pode considerar a prototipagem como uma maneira "mais eficiente" de fazer as coisas, pois mantém uma referência em todas as instâncias, em vez de copiar toda a propriedade em cada objeto. Por outro lado, é um exemplo de acoplamento apertado, que é um grande não-não até que você possa realmente justificar o motivo. thisé bem mais complicado, pois é relevante para o contexto. Você pode encontrar muitos bons recursos gratuitamente na internet.
Dito isso, ambas as formas são apenas ferramentas de linguagem e realmente depende de você e do problema que você está tentando resolver para escolher o que melhor se encaixa.
Se você precisar ter uma propriedade relevante para todas as instâncias de uma classe, use this. Se você precisar ter uma propriedade para funcionar da mesma maneira em todas as instâncias, use prototype.
Atualizar
Em relação aos snippets de amostra, o primeiro é um exemplo de Singleton , portanto, faz sentido usar thisno corpo do objeto. Você também pode melhorar seu exemplo, tornando-o modular assim (e nem sempre é necessário usá-lo this).
/* Assuming it will run in a web browser */
(function (window) {
window.myApp = {
...
}
})( window );
/* And in other pages ... */
(function (myApp) {
myApp.Module = {
...
}
})( myApp );
/* And if you prefer Encapsulation */
(function (myApp) {
myApp.Module = {
"foo": "Foo",
"bar": function ( string ) {
return string;
},
return {
"foor": foo,
"bar": bar
}
}
})( myApp );
Seu segundo snippet não faz muito sentido, porque primeiro você está usando thise depois está tentando hackear prototype, o que não funciona porque thistem prioridade prototype. Não sei ao certo quais eram suas expectativas com relação a esse pedaço de código e como ele estava funcionando, mas eu recomendo que você o refatorasse.
Atualizar
Para elaborar a thisprecedência prototype, posso mostrar um exemplo e explicar como ele pode ser explicado, mas não tenho nenhum recurso externo para fazer backup.
O exemplo é muito simples:
var myClass = function () { this.foo = "Foo"; };
myClass.prototype.foo = "nice try!";
myClass.prototype.bar = "Bar";
var obj = new myClass;
obj.foo; // Still contains "Foo" ...
obj.bar; // Contains "Bar" as expected
A explicação é, como sabemos, thisé relevante para o contexto. Portanto, ele não existirá até que o contexto esteja pronto. Quando o contexto está pronto? Quando a nova instância está sendo criada! Você deve adivinhar o resto agora! Isso significa que, embora exista uma prototypedefinição, mas thisfaz mais sentido ter precedência, porque é tudo sobre a nova instância sendo criada naquele momento.