2010-01-04 19 views
5

Prefiero usar el estilo OOP funcional para mi código (similar al patrón de módulo) porque me ayuda a evitar la palabra clave "nueva" y todos los problemas con el alcance de la palabra clave "this" en devoluciones de llamada.Pregunta sobre el estilo OOP funcional en JavaScript

Pero me he encontrado con algunos problemas menores. Me gustaría utilizar el siguiente código para crear una clase.

namespace.myClass = function(){ 
    var self = {}, 
     somePrivateVar1; 

    // initialization code that would call 
    // private or public methods 
    privateMethod(); 
    self.publicMethod(); // sorry, error here 

    function privateMethod(){} 

    self.publicMethod = function(){}; 

    return self; 
} 

El problema es que no puedo llamar a los métodos públicos desde mi código de inicialización, ya que estas funciones aún no están definidas. La solución obvia sería crear un método init y llamarlo antes de la línea "return self". Pero tal vez conoces una solución más elegante?

Además, ¿cómo manejas la herencia con este patrón? Utilizo el siguiente código, pero me gustaría escuchar sus ideas y sugerencias.

namespace.myClass2 = function(){ 
    var self = namespace.parentClass(), 
     somePrivateVar1;    

    var superMethod = self.someMethod; 
    self.someMethod = function(){ 
    // example shows how to overwrite parent methods 
    superMethod(); 
    }; 

    return self; 
} 

Editar. Para los que preguntó cuáles son las razones para elegir este estilo de programación orientada a objetos, se puede mirar en las preguntas siguientes:

+0

En general, es una mala idea no utilizar las técnicas dadas por un idioma. Eso significa que no debe eludir 'new', así es como se hace en Javascript y probablemente sea la mejor manera _en este idioma en particular_. –

+0

¿Por qué no puedes simplemente definir los métodos en la parte superior, antes de intentar llamarlos? –

+0

Gs, creo que el uso de cierres para crear objetos con miembros privados es una técnica dada por un idioma. Incluso Douglas Crockford lo defiende. También realicé algunas pruebas de rendimiento antes, y para pequeñas cantidades de objetos realmente no importa. (http://valums.com/b/) Pero para mí hace un código más limpio. –

Respuesta

0

Estoy de acuerdo con casi todas comentario o respuesta proporcionada hasta ahora, pero que tomo de Tim respuesta un paso más allá - cuestionó por qué usted quiere llamar a un método antes de que se definió, pero ofrecieron una solución de todos modos, mientras que yo le sugeriría no debería llamada antes de definir (no sé de ningún idioma en que llamar a un método antes de definir o al menos declarar que se considera una buena práctica), entonces ¿qué:

namespace.myClass = function(){ 
    //declare private vars (and self) first 
    var self = {}, 
     somePrivateVar1; 

    //then declare private methods 
    function privateMethod(){} 

    //then public/privileged methods 
    self.publicMethod = function(){}; 

    // THEN (and only then) add your 
    // initialization code that would call 
    // private or public methods 
    privateMethod(); 
    self.publicMethod(); // no error any more 

    //then return the new object 
    return self; 
} 

¿Hay alguna razón en particular por la que esto no funcione para usted?

+0

Gracias, esto funcionará bien, pero preferiría dejar el constructor en la parte superior, ya que es muy común, y no quiero romper los hábitos de otros programadores. –

1

Varias preguntas se me ocurren, tales como por qué desea evitar el operador new, y por qué desea llamar a las funciones antes de que se definan. Sin embargo, dejando a un lado, ¿qué tal algo así como lo siguiente?

namespace.myClass = function(){ 
    var somePrivateVar1; 
    var self = {}; 

    // initialization code that would call 
    // private or public methods 
    privateMethod(); 
    publicMethod(); 

    function privateMethod(){} 
    function publicMethod(){} 

    self.publicMethod = publicMethod; 
    return self; 
} 
+0

Gracias, uno de los problemas con este enfoque es que no tiene una referencia a un objeto actual dentro de su clase. Pero en mi ejemplo, fue posible pasar un objeto a otra función usando la auto variable, ej. someFunctionThatRegistersAnObject (self); –

+0

Intenté votar su respuesta, pero stackoverflow muestra un error "Vote demasiado viejo para ser modificado, a menos que se edite esta respuesta". ¿Es un error? –

+0

@valums: la respuesta ha cambiado para atender su comentario. No estoy seguro del error SO, pero debería poder cambiar su voto ahora que he editado la respuesta. –

0

Esta es la solución que mencioné en la pregunta. Sus comentarios son bienvenidos

namespace.myClass = function(){ 
    var self = {}, 
     somePrivateVar1; 

    function init(){ 
    privateMethod(); 
    self.publicMethod(); 
    } 

    function privateMethod(){} 
    self.publicMethod = function(){}; 

    init(); 
    return self; 
} 
+1

Eso funcionará, y si está comprometido a tener el código de inicialización en la parte superior, antes de declarar cualquiera de sus métodos, sería la única manera de hacerlo, por lo que pude ver. Mi único comentario es que esto no es "elegante", que es lo que ha pedido, sin embargo, mi opinión * personal * es que sus criterios sobre cómo quiere que se "mire" el método no son elegantes de todos modos, así que dentro de este criterio, lo que tienes allí es probablemente la mejor solución. – Graza

2

Puede utilizar Zet.js biblioteca que le ayudará con declarar clases en la forma que desee.

Cuestiones relacionadas