2009-08-11 11 views
8

Quería preguntar sobre las ventajas de mi el siguiente estilo OOP. Escribo mis clases JS de la siguiente manera.¿Es esta una buena manera de hacer JS OOP?

var MyClass = function() { 
    // private vars 
    var self = this, 
     _foo = 1, 
     _bar = "test"; 

    // public vars 
    this.cool = true; 

    // private methods 
    var initialize = function(a, b) { 
     // initialize everything 
    }; 

    var doSomething = function() { 
     var test = 34; 
     _foo = cool; 
    }; 

    // public methods 
    this.startRequest = function() { 

    }; 

    // call the constructor 
    initialize.apply(this, arguments); 
}; 

var instance_1 = new MyClass(); 
var instance_2 = new MyClass("just", "testing"); 

¿Es este un buen enfoque? ¿Hay algún inconveniente? No uso la herencia, pero ¿funcionaría de esta manera para lograr la herencia?

Gracias de antemano.

Respuesta

6

Creo que es un muy buen enfoque. No te avergüences de la cuestión de "no herencia". La mayoría de los OOP no se trata de herencia. Los aspectos más importantes son la encapsulación y el polimorfismo, y los tienes.

Se puede argumentar (bueno, suelo argumentar) que la herencia solo es necesaria para los lenguajes estáticos, donde de alguna manera debe decirle al compilador que estos dos tipos (clases) están relacionados, que tienen algo en común (el ancestro común) para que pueda permitir el polimorfismo. Con los lenguajes dinámicos, OTOH, al compilador no le importará, y el entorno de tiempo de ejecución encontrará las características comunes sin ninguna herencia.

Otro punto: si necesita alguna herencia en algunos lugares (y es gran en algunos casos, como interfaces gráficas de usuario, por ejemplo), a menudo encontrará que puede interoperar fácilmente entre los 'simples' objetos/clases y otros más complejos y pesados. IOW: no intente encontrar un marco que cubra todas sus necesidades y lo use para todo; en su lugar, use el que le resulte más cómodo en cada momento, siempre que ayude con el problema específico.

+0

+1 por - Los aspectos más importantes son la encapsulación y el polimorfismo. – Everyone

+0

+1 aquí también. La herencia ciertamente tiene un peso indebido en muchos artículos sobre OO. Recién comencé a programar en OO productivamente en los últimos años, y ya perdí la cuenta de mis errores de novato causados ​​por herencia excesiva. –

2

En realidad, que no difiere de la forma en que Prototype.js (mi biblioteca favorita) generalmente lo hace. Si mira aquí:

var Class = (function() { 
    function subclass() {}; 

    // All classes are created through Class.create({/*JSON Object*/}); 
    // or Class.create(function, ...properties); 
    // The first form will create a unique class. 
    // The second form will create a Class which subclasses the initial function. 
    function create() { 

    var parent = null, 
        // $A just normalizes the array. 
     properties = $A(arguments); 

    // Which type of class definition was used? 
    if (Object.isFunction(properties[0])) 
     parent = properties.shift(); 

    // This effectively creates a constructor 
    function klass() { 
     this.initialize.apply(this, arguments); 
    } 

    // Allows klass to have addMethods property 
    Object.extend(klass, Class.Methods); 
    klass.superclass = parent; 
    klass.subclasses = []; 

    // Does this class have a parent class? 
    if (parent) { 
     subclass.prototype = parent.prototype; 
     klass.prototype = new subclass; 
     parent.subclasses.push(klass); 
    } 

    // Add methods to the class 
    for (var i = 0; i < properties.length; i++) 
     klass.addMethods(properties[i]); 

    // emptyFunction = function(){}; 
    if (!klass.prototype.initialize) 
     klass.prototype.initialize = Prototype.emptyFunction; 

    // Creates the constructor 
    klass.prototype.constructor = klass; 
    return klass; 
    } 

    function addMethods(source) { 
    // Does this class have a parent? 
    var ancestor = this.superclass && this.superclass.prototype; 

    // Grab the keys of a JSON object 
    var properties = Object.keys(source); 

    // Makes sure each object has a toString and valueOf method. 
    if (!Object.keys({ toString: true }).length) { 
     if (source.toString != Object.prototype.toString) 
     properties.push("toString"); 
     if (source.valueOf != Object.prototype.valueOf) 
     properties.push("valueOf"); 
    } 

    //Loop through the properties. 
    for (var i = 0, length = properties.length; i < length; i++) { 

     // property is the Key in the JSON, value is the corresponding 
     // method or property value. 
     var property = properties[i], value = source[property]; 
     if (ancestor && Object.isFunction(value) && 
      value.argumentNames().first() == "$super") { 

     // Handles an override of a parent method. 
     var method = value; 
     value = (function(m) { 
      return function() { return ancestor[m].apply(this, arguments); }; 
     })(property).wrap(method); 

     value.valueOf = method.valueOf.bind(method); 
     value.toString = method.toString.bind(method); 
     } 
     this.prototype[property] = value; 
    } 

    return this; 
    } 

    // And here is the final value! 
    return { 
    create: create, 
    Methods: { 
     addMethods: addMethods 
    } 
    }; 
})(); 

La ventaja de lo anterior es que podrá administrar la herencia de forma rápida y fácil. En su caso, la herencia (o, al menos, funciones primordiales) es casi imposible sin crear alguna forma de función de ayuda externa como la de arriba.

0

Si está buscando una estructura de herencia basada en clases más dentro de JavaScript, es posible que desee consultar Dojo.

0

También puede utilizar literales y constructores.De esta manera no tienes que utilizar los conceptos menos atractivos en Javascript: prototype, new-statement y this-keyword.

La receta básica es simple:

  • crear una función que construye un objeto literal
  • poner esa función en un objeto literal

El literal que tiene los actos constructor como una clase . Las funciones del constructor actúan como un constructor y el literal producido actúa como una instancia de clase.

Aquí se muestra un ejemplo:

Car = { 
    createNew:function() { //no prototype! 
     var obj = {}; 
     var color; 
     obj.setColor = function(c) { color = c; } 
     obj.drive = function(){ alert('driving a '+color+' car'); } 
     return obj; //no this-keyword! 
    } 
} 

var car = Car.createNew(); //no new statement! 
car.setColor('red'); 
car.drive(); 

Más documentos se pueden encontrar aquí:

http://www.gabordemooij.com/jsoop.html

y aquí

https://github.com/schuttelaar/Rococo2/wiki/Getting-started

Cuestiones relacionadas