La primera diferencia se puede resumir como: this
se refiere a la Instancia de la clase. prototype
se refiere a Definición .
Digamos que tenemos la siguiente clase:
var Flight = function ( number ) { this.number = number; };
Así que aquí adjuntamos this.number
a cada instancia de la clase, y tiene sentido porque cada Flight
debería tener su propio número de vuelo.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
En contraste, prototype
define una propiedad única a la que pueden acceder todas las instancias.
Ahora, si queremos obtener el número de vuelo, simplemente podemos escribir el siguiente fragmento de código y todas nuestras instancias obtendrán una Referencia para este objeto con un nuevo prototipo.
Flight.prototype.getNumber = function () { return this.number; };
La segunda diferencia es sobre la forma en que JavaScript busca una propiedad de un objeto. Cuando busca Object.whatever
, JavaScript va hasta el objeto principal Object (el objeto del que todo lo demás ha heredado), y tan pronto como encuentre una coincidencia, regresará o llámalo.
Pero eso solo sucede con las propiedades prototipadas. Entonces, si tienes un lugar en los niveles más altos this.whatever
, JavaScript no lo considerará como una coincidencia y continuará la búsqueda.
Veamos cómo sucede en la realidad.
Primero, tenga en cuenta que [casi] todo son Objetos en JavaScript. Prueba esto:
typeof null
Ahora veamos lo que está dentro de un Object
(note la mayúscula O
y .
al final). En las Herramientas de desarrollo de Google Chrome, cuando ingrese .
obtendrá una lista de propiedades disponibles dentro de ese objeto específico.
Object.
Ahora haga lo mismo para Function
:
Function.
Puede observar el método name
. Solo ve y enciéndelo y veamos que pasa:
Object.name
Function.name
Ahora vamos a crear una función:
var myFunc = function () {};
Y veamos si también obtuvimos el método name
aquí:
myFunc.name
Deberías obtener una cadena vacía, pero está bien. No debes obtener un error o excepción.
Ahora, agreguemos algo a ese Object
parecido a un dios y veamos si lo obtenemos en otros lugares también.
Object.prototype.test = "Okay!";
Y ahí tienes:
Object.prototype.test
Function.prototype.test
myFunc.prototype.test
En todos los casos debería ver "Okay!"
.
En cuanto a los pros y los contras de cada método, puede considerar la creación de prototipos como una forma "más eficiente" de hacer las cosas, ya que mantiene una referencia en cada instancia en lugar de copiar la propiedad completa en cada objeto. Por otro lado, es un ejemplo de Tightly Coupling que es un gran no-no hasta que realmente puedas justificar la razón. this
es bastante más complicado ya que es relevante para el contexto. Puede encontrar una gran cantidad de buenos recursos de forma gratuita en Internet.
Dicho de otra manera, ambas formas son solo herramientas de lenguaje y realmente dependen de ti y del problema que intentas resolver para elegir lo que mejor se ajusta.
Si necesita tener una propiedad que sea relevante para cada instancia de una clase, entonces use this
. Si necesita tener una propiedad para funcionar igual en cada instancia, entonces use prototype
.
Actualizar
Con respecto a los fragmentos de muestra, el primero es un ejemplo de Singleton , por lo que tiene sentido usar this
dentro del cuerpo del objeto. También puedes mejorar tu ejemplo haciéndolo modular así (y no necesitas usar siempre también 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 );
Tu segundo fragmento de código no tiene mucho sentido porque primero estás usando this
y luego intentas hackearlo con prototype
, lo que no funciona porque this
tiene prioridad sobre prototype
. No estoy seguro de cuáles eran sus expectativas con respecto a ese código y de cómo funcionaba, pero le recomiendo que lo refactorice.
Actualizar
Para desarrollar más detalladamente que this
tiene prioridad sobre prototype
, puedo mostrarle un ejemplo y explicarle cómo se puede explicar, pero no tengo ningún recurso externo para respaldarlo.
El ejemplo es muy simple:
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
La explicación es, como sabemos, this
es relevante para el contexto. Así que no llegará a existir hasta que el contexto esté listo. Cuando el contexto está listo? Cuando se está creando la nueva instancia! ¡Deberías adivinar el resto ahora! Esto significa que aunque hay una definición prototype
, pero this
tiene más sentido tener prioridad porque se trata de la nueva instancia que se está creando en ese momento.