hacer es6 definir constructores como clases javascript oop constructor class-design

es6 - function constructor javascript



Patrón de constructor OO Javascript: neoclásico vs prototipo (7)

¿Usas este tipo de patrón de constructor?

He usado este patrón más temprano cuando estaba aprendiendo JavaScript y tropecé con la literatura de Douglas Crockford.

¿Lo encuentras comprensible?

Mientras entiendas los cierres, este método es claro.

¿Tienes uno mejor?

Depende de lo que estás tratando de lograr. Si intentas escribir una biblioteca que sea tan idiota como sea posible, entonces puedo entender completamente el uso de variables privadas. Puede ayudar a evitar que los usuarios alteren inadvertidamente la integridad de su objeto. Sí, el costo a tiempo podría ser un poco mayor (aproximadamente 3 veces más grande), pero el costo del tiempo es un argumento discutible hasta que realmente afecte su aplicación. Noté que la prueba mencionada en una publicación anterior ( gist.github.com/244166 ) no cuenta por cuánto tiempo se necesita para acceder a las funciones de un objeto.

Descubrí que el método de prototipo / constructor generalmente conduce a un tiempo de construcción más rápido, sí, pero no necesariamente ahorra tiempo en la recuperación. Hay un costo adicional de usar la cadena de prototipos para encontrar una función versus tener una función unida directamente al objeto que está utilizando. Entonces, si llama a muchas funciones de prototipo y no construye muchos objetos, podría tener más sentido usar el patrón de Crockford.

Sin embargo, no me gusta usar variables privadas, si no estoy escribiendo mi código para una gran audiencia. Si estoy con un equipo de personas que son codificadores capaces, generalmente puedo confiar en que sabrán cómo usar mi código si codigo y comento bien. Luego utilizo algo similar al patrón de Crockford sin miembros / métodos privados.

Vi una conferencia de Douglas Crockford sobre las partes buenas en Javascript y mis ojos se abrieron. En un momento dijo, algo así como, "Javascript es el único lenguaje en el que los buenos programadores creen que pueden usarlo efectivamente, sin aprenderlo". Entonces me di cuenta, soy ese tipo.

En esa charla, hizo algunas declaraciones que, para mí, fueron bastante sorprendentes y perspicaces. Por ejemplo, JavaScript es el lenguaje de programación más importante del planeta. O es el idioma más popular en el planeta. Y, que está roto de muchas maneras serias.

La declaración más sorprendente que hizo, para mí, fue "lo nuevo es peligroso". Él no lo usa más. Él no usa this tampoco.

Presentó un patrón interesante para un constructor en Javascript, uno que permite variables de miembros privados y públicos, y no se basa en ninguno new , ni this . Se parece a esto:

// neo-classical constructor var container = function(initialParam) { var instance = {}; // empty object // private members var privateField_Value = 0; var privateField_Name = "default"; var privateMethod_M1 = function (a,b,c) { // arbitrary }; // initialParam is optional if (typeof initialParam !== "undefined") { privateField_Name= initialParam; } // public members instance.publicMethod = function(a, b, c) { // because of closures, // can call private methods or // access private fields here. }; instance.setValue = function(v) { privateField_Value = v; }; instance.toString = function(){ return "container(v=''" + privateField_Value + "'', n=''" + privateField_Name + "'')"; }; return instance; } // usage var a = container("Wallaby"); WScript.echo(a.toString()); a.setValue(42); WScript.echo(a.toString()); var b = container(); WScript.echo(b.toString());

EDITAR : código actualizado para cambiar al nombre de la clase en minúsculas.

Este patrón ha evolucionado a partir de los modelos de uso anteriores de Crockford .

Pregunta: ¿Usas este tipo de patrón de constructor? ¿Lo encuentras comprensible? ¿Tienes uno mejor?


¿Usas este tipo de patrón de constructor?

Nope

¿Lo encuentras comprensible?

Sí, es muy directo.

¿Tienes uno mejor?

No he visto la charla todavía, pero la abordaré en breve. Hasta entonces, no veo el peligro de usar new y this , y he aquí por qué:

Sin haber escuchado sus puntos, solo puedo suponer que sugiere mantenerse alejado de tales cosas debido a la naturaleza de this , y cómo es propenso a cambiar dependiendo del contexto en el que se ejecuta un método en particular (directamente sobre el objeto original o como una devolución de llamada, etc.). Como educador, puede estar enseñando a evitar estas palabras clave debido a la demografía de desarrolladores en gran parte inconscientes e inexpertos que incursionan en JavaScript sin comprender primero la naturaleza del idioma. Para desarrolladores experimentados que están íntimamente familiarizados con el idioma, no estoy convencido de que sea necesario evitar esta característica del lenguaje, que le otorga una increíble cantidad de flexibilidad (que es completamente diferente de evitar cosas como). Dicho todo eso, lo estaré viendo ahora.

En cualquier caso, cuando no estoy utilizando algún tipo de marco que soporte herencia dojo.declare (como dojo.declare ), o cuando escribo un objeto independiente del marco, actualmente tomo el siguiente enfoque.

Definición:

var SomeObject = function() { /* Private access */ var privateMember = "I am a private member"; var privateMethod = bindScope(this, function() { console.log(privateMember, this.publicMember); }); /* Public access */ this.publicMember = "I am a public member"; this.publicMethod = function() { console.log(privateMember, this.publicMember); }; this.privateMethodWrapper = function() { privateMethod(); } };

Uso :

var o = new SomeObject(); o.privateMethodWrapper();

Donde bindScope es una función de utilidad similar a dojo.hitch de Dojo o Function.prototype.bind de Prototype.


Creo que puede ayudar a la discusión a informar aquí cuál es el punto principal sobre este patrón, tal como lo explica Douglas Crockford en su video de presentación "JavaScript avanzado".

El punto principal es evitar el uso del nuevo operador. Porque cuando alguien olvida usar el nuevo operador cuando llama a una función del constructor de objetos, los miembros del objeto agregados en el constructor terminan en el espacio de nombres global. Tenga en cuenta que en este caso no hay advertencia o error en tiempo de ejecución que informe el error, el espacio de nombres global simplemente se contamina. Y esto ha demostrado tener serias implicaciones de seguridad y ser fuente de muchos errores difíciles de diagnosticar.

Ese es el punto principal de este patrón Powerconstructor.

La parte privada / privilegiada es secundaria. Está bien hacer eso de otra manera. Entonces, los miembros del prototipo no se usan.

HTH luKa


En su libro se llama herencia funcional (página 52). No lo uso todavía Es comprensible si aprendes javascript de Douglas. No creo que haya un mejor enfoque. Este es bueno porque:

  • permite a un programador crear miembros privados

  • asegura a los miembros privados y elimina esta oposición a la privacidad pretendida (los miembros privados comienzan con _)

  • hace que la herencia sea fluida y sin código innecesario

Sin embargo, tiene algunos inconvenientes. Puede leer más sobre esto aquí: http://www.bolinfest.com/javascript/inheritance.php


Esto se parece a la versión no única del patrón del módulo , mediante el cual se pueden simular variables privadas aprovechando los "cierres" de JavaScript.

Me gusta ( un poco ... ). Pero realmente no veo la ventaja en las variables privadas hechas de esta manera, especialmente cuando significa que cualquier método nuevo agregado (después de la inicialización) no tiene acceso a las variables privadas.

Además, no aprovecha el modelo prototípico de JavaScript. Todos sus métodos y propiedades deben inicializarse CADA vez que se llama al constructor; esto no ocurre si tiene métodos almacenados en el prototipo del constructor. ¡El hecho es que usar el patrón de constructor / prototipo convencional es mucho más rápido! ¿De verdad crees que las variables privadas hacen que el éxito del desempeño valga la pena?

Este tipo de modelo tiene sentido con el patrón del módulo porque solo se inicializa una vez (para crear un pseudo-singleton), pero no estoy tan seguro de que tenga sentido aquí.

¿Usas este tipo de patrón de constructor?

No, aunque utilizo su variante singleton, el patrón del módulo ...

¿Lo encuentras comprensible?

Sí, es legible y bastante claro, pero no me gusta la idea de agrupar todo dentro de un constructor como ese.

¿Tienes uno mejor?

Si realmente necesita variables privadas, apéguese a ellas por todos los medios. De lo contrario, simplemente use el patrón de constructor / prototipo convencional (a menos que comparta el miedo de Crockford al new / this combo ):

function Constructor(foo) { this.foo = foo; // ... } Constructor.prototype.method = function() { };

Otras preguntas similares relacionadas con las opiniones de Doug sobre el tema:


Evito este patrón ya que a la mayoría de las personas les resulta más difícil de leer. Generalmente sigo dos enfoques:

  1. Si solo tengo uno de algo, entonces uso objetos anónimos:

    var MyObject = { myMethod: function() { // do something } };

  2. Para más de uno de algo, utilizo la herencia prototípica javascript estándar

    var MyClass = function() { }; MyClass.prototype.myMethod = function() { // do something }; var myObject = new MyClass();

(1) es mucho más fácil de leer, entender y escribir. (2) es más eficiente cuando hay múltiples objetos. El código de Crockford creará una nueva copia de las funciones dentro del constructor cada vez. El cierre también tiene la desventaja de ser más difícil de depurar.

Aunque se pierden variables verdaderamente privadas, se prefija _ como supuestas convenciones a los miembros supuestamente privados.

this es un problema ciertamente difícil en javascript, pero se puede .call utilizando .call y .apply para configurarlo correctamente. También a menudo uso var self = this; para crear una variable de cierre para usar como funciones internas dentro de una función miembro.

MyClass.prototype.myMethod = function() { var self = this; // Either function inner1() { this.member(); } inner1.call(this); // Or function inner2() { self.member(); } inner2(); };


Si necesitamos crear siempre el mismo tipo de objeto, prefiero usar el patrón de constructor Prototypal , ya que permite compartir métodos y propiedades a través de la delegación automática a través de la cadena de prototipos .

También podemos mantener los objetos privados; mira este enfoque:

var ConstructorName = (function() { //IIFE ''use strict''; function privateMethod (args) {} function ConstructorName(args) { // enforces new (prevent ''this'' be the global scope) if (!(this instanceof ConstructorName)) { return new ConstructorName(args); } // constructor body } // shared members (automatic delegation) ConstructorName.prototype.methodName = function(args) { // use private objects }; return ConstructorName; }());

Recomiendo revisar esta respuesta donde podemos encontrar una forma interesante de crear una función de constructor: Diferente forma de crear un objeto Javascript

Este es un ejemplo donde puede usar el enfoque del constructor de prototipos: ¿Cómo creo un error personalizado en JavaScript?