La primera diferencia se puede resumir como: se this
refiere a la instancia de la clase. prototype
se refiere a la definición .
Digamos que tenemos la siguiente clase:
var Flight = function ( number ) { this.number = number; };
Así que aquí estamos adjuntando this.number
a cada instancia de la clase, y tiene sentido porque cada uno Flight
debe tener su propio número de vuelo.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
Por el contrario, 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 y todas nuestras instancias obtendrán una referencia a este objeto recién 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 está buscando Object.whatever
, JavaScript llega hasta el objeto Object principal (el objeto del que todo lo demás ha heredado), y tan pronto como encuentre una coincidencia, regresará o lo llamará.
Pero eso solo sucede para las propiedades prototipadas. Entonces, si tiene algún 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 qué hay dentro de Object
(tenga en cuenta las mayúsculas O
y .
al final). En las Herramientas para desarrolladores 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.
Puedes notar el name
método. Solo ve y enciéndelo y veamos qué sucede:
Object.name
Function.name
Ahora creemos una función:
var myFunc = function () {};
Y veamos si también tenemos el name
método aquí:
myFunc.name
Deberías obtener una cadena vacía, pero está bien. No debe obtener un error o una excepción.
¿Ahora agreguemos algo a ese dios Object
y veamos si lo obtenemos también en otros lugares?
Object.prototype.test = "Okay!";
Y ahí vas:
Object.prototype.test
Function.prototype.test
myFunc.prototype.test
En todos los casos deberías ver "Okay!"
.
Con respecto 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 toda la propiedad 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 muchos buenos recursos gratis en Internet.
Dicho todo esto, ambas formas son solo herramientas de lenguaje y realmente depende de usted y del problema que está tratando de resolver para elegir lo que mejor se adapte.
Si necesita tener una propiedad que sea relevante para cada instancia de una clase, utilice 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 usarlo this
dentro del cuerpo del objeto. También puede mejorar su ejemplo haciéndolo modular de esta manera (y no necesita usarlo siempre this
también).
/* 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 );
Su segundo fragmento no tiene mucho sentido porque primero lo está utilizando this
y luego está intentando piratearlo prototype
, lo que no funciona porque this
tiene prioridad prototype
. No estoy seguro de cuáles eran sus expectativas de ese código y cómo funcionaba, pero le recomiendo que lo refactorice.
Actualizar
Para dar más detalles sobre cómo this
tener prioridad prototype
, puedo mostrarle un ejemplo y decirle 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. Entonces, no llegará a existir hasta que el contexto esté listo. Cuando el contexto está listo? Cuando se crea la nueva instancia! ¡Deberías adivinar el resto ahora! Significa que, aunque existe una prototype
definición, this
tiene más sentido tener prioridad porque se trata de la nueva instancia que se está creando en ese momento.