2012-05-08 11 views
13

¿Es este código,JavaScript POO: definición del método con o sin "prototipo"

function Person() { 
    function myMethod() { 
     alert ('hello'); 
    } 
    this.method = myMethod; 
} 

equivalente a:

function Person() { } 
Person.prototype.method2 = function() { 
    alert ('hello'); 
}; 

Si es así, que la definición del método debería utilizar y por qué?

+1

posible duplicado de [Uso de 'prototipo' frente a 'esto' en Javascript?] (Http://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript) –

+0

[ declarando javascript método de objeto en el vs. función constructora de prototipo] (http://stackoverflow.com/questions/9772307/declaring-javascript-object-method-in-constructor-function-vs-in-prototype) –

Respuesta

13

están funcionalmente equivalente en su ejemplo sencillo, pero detrás de las escenas de trabajo de manera muy diferente. La propiedad prototype en una función es realmente la "plantilla de prototipo". Dice "cada vez que se hace un objeto y me utilizan como constructor del objeto, les doy este objeto como su prototipo".

Así que todos los Person s creados en su segundo ejemplo comparten la misma copia del método method2.

En el primer ejemplo, cada vez que el intérprete se encuentra con la palabra clave function, entonces se crea un nuevo objeto de función. Por lo tanto, en el primer ejemplo, cada instancia de Person tiene su propia copia del método myMethod. La gran mayoría de las veces esto no importa. Pero este primer enfoque usa más memoria y, a veces, eso sí importa.

Ellos no son funcionalmente equivalentes en los casos más interesantes. En el primer ejemplo, myMethod puede acceder a las variables locales definidas en Person, pero el segundo ejemplo no puede, como una diferencia.

+0

¿Conoce un caso/contexto donde el primer método sería más útil? Gracias. –

+2

La primera situación le permite tener variables "privadas". Se puede acceder a cualquier variable local definida en el método 'Persona 'mediante' myMethod', pero por ninguna otra cosa. Recomiendo leer Crockford's * JavaScript the Good Parts *, ya que entra en este patrón con gran detalle. –

0

No, no son equivalentes. Aunque, son similares. El primer método creará una nueva función myMethod para cada new Person() creado.

El segundo método tendrá una función method2 que es "compartida" por todos Person's.

2

En el primer escenario, cuando crea una nueva persona, var person1 = new Person();, tendrá su propia copia de myMethod. Si crea objetos de 100 personas, cada uno tendrá su propia copia de este método.

El uso de un prototipo, cada nuevo objeto persona compartirá la definición del método. Esto es mucho más eficiente desde el punto de vista de la memoria, ya que solo habrá una copia del método.

Si usted está planeando tener varios objetos Persona, la segunda manera es mejor .. pero si sólo hay unos pocos objetos de un persona, no importará mucho.

+0

Si el método no prototipo se hizo popular, entonces tal vez los tiempos de ejecución de javascript optimizarían la diferencia ... –

+0

Ciertamente encuentro que el método no prototipo es más legible. – Kokodoko

0

Ellos tienen una funcionalidad similar pero debería utilizar el segundo método (prototipo), porque cuando se va a crear un objeto utilizando new Person() cada objeto compartirán el mismo method2 pero utilizando el primer enfoque cada nuevo objeto tendrá su propia myMethod() que consumirá moe memoria.

Hace unos días hice una pregunta similar y obtuvethis answer.

1

No es totalmente equivalente.

En ambos casos, se define una función (constructor) Person() en el espacio de nombres global.

En el primer caso, define una nueva función myMethod() en un cierre dentro de la función Person(). Normalmente, la función myMethod() no estaría disponible después de la función/constructor Person() acabados. Sin embargo, en este caso, lo asigna al this.method. Por lo tanto, cuando se ejecuta el constructor se crea

var myPerson = new Person(); 

Un nuevo objeto, entonces la función se llama con Person()this conjunto al nuevo objeto. Por lo tanto, el nuevo objeto recibe un campo method con myMethod función fijado a ella.

En el segundo caso, method2 se define dentro del Person.prototype. En este caso, cuando se llama

var myPerson = new Person(); 

no habrá ningún campo definido directamente dentro de su nuevo objeto (como usted no hace nada con this en la función Person). Sin embargo, cada objeto contiene una referencia a su prototipo. Si el objeto se crea llamando Person(), esta referencia se establece en Person.prototype. Por lo tanto, su objeto contendrá finalmente method2, aunque no directamente en sí mismo, sino en el prototipo. Así que cuando se llama a

myPerson.method2(); 

el intérprete busca method2 dentro del objeto myPerson y no encuentra nada, entonces se ve en el prototipo de myPerson, que es Person.prototype y se encuentra method2, por lo que lo llama.

Larga historia corta: en la primera el constructor crea el método, por lo que cada vez que se llama al constructor, se crea un nuevo método y se inserta al nuevo objeto. En el segundo caso, el método se almacena en el prototipo, por lo que cada objeto que cree tendrá la referencia a la misma instancia de su método.

+0

Debido a la búsqueda, el rendimiento inteligente sería el primer método más rápido? –

+1

@ Jean-PhilippeMartin Sí. Obtiene una búsqueda de método más rápida, pero mucho más uso de memoria. Las diferencias de rendimiento deberían ser visibles en las llamadas repetidas con cadenas prototipo largas. En este caso simple, sin embargo, probablemente no haya nada de qué preocuparse. – Imp

+0

Tengo un caso de prueba para la prueba de comparación de rendimiento del enfoque: http://jsperf.com/method-definition-with-or-without-prototype –

Cuestiones relacionadas