¿Por qué los methods de instancia se definen en el prototipo pero los campos de instancia se definen en el constructor?

Al hacer inheritance en JavaScript, el patrón que siempre veo define los methods de instancia en el prototipo, pero los campos de instancia en el constructor (ver ejemplo a continuación). ¿Cuál es la motivación para esto? ¿Por qué no ser consistente y definir ambos en el prototipo?

function MyClass() { this.myField = 0; // why this... } MyClass.prototype.myField = 0; // ...instead of this? 

Explicación

Porque las properties prototipo se comparten entre todas las instancias, ya que cada instancia tiene una reference al mismo object prototipo.

Esto no es un problema con los types inmutables, podrías hacer:

 MyClass.prototype.myField = 0; var a = new MyClass(); a.myField = 42; 

y solo a tendría este valor. Esto se debe a que la asignación crea la propiedad myField para a . Puede probar esto llamando a a.hasOwnProperty('myField') antes y después de la asignación.

Pero si tienes objects o matrices

 MyClass.prototype.myField = []; 

y solo se agrega a esa matriz y no asigna una nueva matriz (como a.myField = [] ), entonces cada instancia tiene el nuevo valor en esa matriz.


Solución

Debe inicializar matrices y objects en el constructor, de modo que cada instancia obtenga su propio object o instancia de matriz. Algunas pautas de estilo proponen que sigas creando la propiedad en el prototipo, pero la inicializas con null . Esto no tiene otro beneficio que agregar alguna estructura conceptual (si tal palabra existe) a su código.

Por ejemplo:

 function MyClass() { this.myField = []; } /** * @type {Array} */ MyClass.prototype.myField = null;