Configuración de métodos a través del objeto prototipo o en constructor, ¿diferencia? [duplicar]

StackOverflow https://stackoverflow.com/questions/422476

Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

¿Podría explicar la diferencia entre los métodos de configuración en el constructor y mediante el objeto prototipo? El siguiente código muestra estas dos formas de configurar los métodos: say_hello y say_bye ambos funcionan bien:

function MessageClass() {
  this.say_bye = function() { alert('see ya'); };
}

MessageClass.prototype.say_hello = function() { alert('hello'); };

x = new MessageClass();
x.say_hello();
x.say_bye();
¿Fue útil?

Solución

foxxtrot y annakata son correctos, pero lanzaré mis 2 centavos.

Si usa el prototipo, entonces cada instancia de " MessageClass " Realmente está haciendo referencia a las mismas funciones. Las funciones existen en la memoria solo una vez y se utilizan para todas las instancias. Si declara los métodos en el constructor (o si lo agrega a una instancia específica) en lugar del prototipo, se creará una nueva función para cada instancia de MessageClass.

Dicho esto, es probable que no haya una diferencia de rendimiento notable en la mayoría de los casos y es poco probable que vea una diferencia en el uso de la memoria. Me gustaría ir con el método de prototipo a menos que tenga una razón convincente para hacer lo contrario. La única razón por la que puedo pensar que es posible que desee declarar un método en el constructor es si necesita un cierre. Por ejemplo, si tiene controladores de eventos o si desea simular propiedades privadas con captadores / definidores, podría hacerlo:

function MessageClass() {
    var self = this;
    this.clickHander = function(e) { self.someoneClickedMe = true; };

    var _private = 0;
    this.getPrivate = function() { return _private; };
    this.setPrivate = function(val) { _private = val; };
}

EDITAR: Debido a que se ha discutido cómo este objeto de efectos se extiende por otro objeto con funciones asignadas en el constructor, estoy agregando un poco más de detalle. Podría usar el término " clase " para simplificar la discusión, pero es importante tener en cuenta que js no admite clases (eso no significa que no podamos hacer un buen desarrollo de OO) o no estaríamos discutiendo este tema.

La mayoría de las bibliotecas de javascript llaman al constructor en la clase base y la subclase. (por ejemplo, Object.extend de Prototype.js) Esto significa que los métodos asignados en el constructor de cada uno estarán disponibles en los objetos resultantes. Sin embargo, si usted mismo está extendiendo objetos, puede haber consecuencias inesperadas.

Si tomo el MessageClass arriba y lo extiendo:

function ErrorMessageClass() {}
ErrorMessageClass.prototype = new MessageClass();

errorMsg = new ErrorMessageClass();

Entonces errorMsg tendrá los métodos getPrivate y setPrivate, pero es posible que no se comporten como cabría esperar. Debido a que esas funciones estaban en el ámbito cuando fueron asignadas (es decir, en " ErrorMessageClass.prototype = new MessageClass () " no solo se comparten los métodos get / setPrivate, la variable _private se comparte en todas las instancias de ErrorMessageClass también. _private una propiedad estática para ErrorMessageClass. Por ejemplo:

var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'A'
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'B'

Del mismo modo con la función clickHandler y la propiedad someoneClickedMe:

errorA.clickHandler();
console.log(errorA.someoneClickedMe); // prints 'true'
console.log(errorB.someoneClickedMe); // prints 'true'

Sin embargo, cambie las definiciones de funciones para usar this._private:

this.getPrivate = function() { return this._private; };
this.setPrivate = function(val) { this._private = val; };

y el comportamiento de las instancias de ErrorMessageClass se convierte en más de lo que cabría esperar:

errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'B'

Otros consejos

Si vincula los métodos con el prototipo JS solo tiene que hacerlo una vez y se enlaza con una clase de objeto (lo que hace que sea elegible para las extensiones OO JS).

Si realiza el enlace dentro de la clase " " función, JS tiene que hacer el trabajo de crear y asignar para cada instancia.

La diferencia es cuando se deriva una clase de la clase de mensaje. Solo los métodos declarados en el prototipo estarán disponibles en las clases secundarias de Mensaje.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top