¿Hay alguna diferencia entre la function del constructor y el object prototipo al usar la inheritance?

Considere lo siguiente con los fragments de JavaScript:

function foo() { this.bar = function() { }; } // or... (if we used an empty constructor function) foo.prototype.bar = function() { }; 

¿Cuál es la diferencia cuando hago esto?

 function baz() { } baz.prototype = new foo(); 

En ambos casos, baz termina teniendo una bar miembro bar pero ¿cuál es la diferencia? ¿Por qué debería hacer esto en diferentes lugares?

La diferencia es donde en la cadena de prototypes se encuentra la propiedad.

Suponiendo que tenemos f = new foo(); b = new baz() . Entonces tenemos las siguientes situaciones:

Definición de foo sin usar un prototipo:

 +-----------+ +---------------+ | f | | foo.prototype | | __proto__-+---->| constructor | | bar | | | +-----------+ +---------------+ 

bar es una propiedad del object mismo ( f.howOwnProperty('bar') devuelve true ).

Si asigna la propiedad al prototipo, la situación es:

 +-----------+ +---------------+ | f | | foo.prototype | | __proto__-+---->| constructor | | | | bar | +-----------+ +---------------+ 

f no tiene su propia bar properties, pero la propiedad se comparte con todas las demás instancias de foo .

Similar para el segundo fragment, que da como resultado

 +-----------+ +---------------+ +---------------+ | b | | foo instance | | foo.prototype | | __proto__-+---->| __proto__ -+---->| constructor | | | | bar | | | +-----------+ +---------------+ +---------------+ 

o

 +-----------+ +---------------+ +---------------+ | b | | foo instance | | foo.prototype | | __proto__-+---->| __proto__ -+---->| constructor | | | | | | bar | +-----------+ +---------------+ +---------------+ 

¿Por qué quieres hacer esto?

Se trata principalmente de estructura y no desperdicio de memory. Puede agregar funciones a un object en una function de constructor:

 function Foo() { this.bar = function() {}; } 

pero esto también significa que cada instancia de Foo tiene su propia function, es decir, f1.bar === f2.bar es false , aunque ambas funciones están haciendo exactamente lo mismo.

El uso del prototipo le brinda una manera limpia de separar las properties comunes a todas las instancias y las específicas de la instancia.

Al final, es inheritance "justa", que es un concepto en el desarrollo de software (como la agregación) y puede usarse donde sea que tenga sentido. Su segundo fragment básicamente significa que un baz es un foo , por lo que una instancia de baz , además de sus propias properties, tiene las mismas properties que una instancia de foo (henetworkingada).

Una gran diferencia es que si cambia las properties del prototipo, esos cambios se aplicarán a todas las instancias, incluidas las que ya existen, mientras que si cambia una propiedad que se creó en el constructor, solo la cambiará para la instancia en la que la cambie. .

En cuanto a lo que algunas de las otras respuestas dijeron sobre establecer bar en el constructor resultando en que cada instancia tenga su propia copy de la function: eso es cierto si tienes una expresión de function dentro del constructor como se muestra en el código en la pregunta, pero no es verdad si usted asigna una reference de function como esta:

 function myFunction() {} function foo() { this.bar = myFunction; } 

En ese caso, todas las instancias tendrán una propiedad de bar que haga reference a la misma function, pero una instancia individual aún podría tener su propiedad de bar asignada a otra cosa sin afectar otras instancias.

Para agregar a las respuestas existentes:

Hacer una function prototipo permitiría que los cambios se henetworkingen. es decir, si escribes

 function foo(){} foo.prototype.bar = function(){return 1}; function baz(){} baz.prototype = new foo(); new baz().bar(); //returns 1 foo.prototype.bar = function(){return 2}; new baz().bar(); //returns 2 

Sin embargo, ponerlo en el constructor permitiría que otros objects que lo henetworkingan también "tengan" esa function, pero la function no se henetworkinga.

 function foo(){this.bar = function(){return 1};} function baz(){} baz.prototype = new foo(); new baz().bar(); //returns 1 foo.prototype.bar = function(){return 2}; new baz().bar(); //returns 1 

Creo que estoy respondiendo la pregunta correcta aquí, si no, házmelo saber.

La diferencia es que el uso de prototypes da como resultado solo 1 instancia.

Entonces, por ejemplo, baz.bar en una instancia es lo mismo que baz.bar en otra. Compartirán valores dentro de la instancia 'foo':

 function foo() { var x = 0; this.bar = function() {}; this.getVal = function() { return x; } this.setVal = function(val) { x = val; } } function baz() {} baz.prototype = new foo(); var a = new baz(), b = new baz(); a.setVal("1234") console.log(b.getVal()); // prints '1234' 

http://jsfiddle.net/jonathon/7GtRD/

Si b llamaran directamente 'foo', entonces no compartirían los valores dentro del foo . Sin embargo, aquí es donde difiere ligeramente entre la configuration de this.bar y el uso del prototipo para crear la barra.

Usar el prototipo crearía una instancia de bar . Entonces a.bar será lo mismo que b.bar . Si lo haces de la otra manera, serán dos funciones diferentes (haciendo lo mismo).