Expansión de objetos con variables y métodos privados

Continuando con el apasionante mundo de la creación de objetos en javascript y después de haber aprendido a usar los getters y los setters, me he puesto a definir objetos y quería que todos ellos tuvieran la función de vincularse unos con otros.

Al hacer esto me he visto repitiendo una y otra vez el mismo código para realizar esa vinculación, lo cual no es buen sintoma. Así que me he parado a pensar cómo podría hacer para crear un objeto genérico con esas propiedades para que los demás objetos, por así decirlo, hereden esas propiedades.

Me he puesto manos a la obra y lo primero que he hecho ha sido crear la definición de ese objeto genérico que va a contener, de momento, solo la funcionalidad de vincular.


var Objeto = function() {
    var self = this;

    self._binds = {};

    self.clase = {
      bind: function(v, o, f) {
        self._binds[v] || (self._binds[v] = []);
        self._binds[v].push({
          obj: o,
          func: f
        });
      }
    };

    self._bind = function() {
      self._binds['value'] && self._binds['value'].forEach(function(e) {
        e.func.apply(e.obj, [self.clase]);
      });
    };
  };

Después de tener el objeto genérico y sabiendo que no voy a instanciar ningún objeto real con él, sino que lo voy a usar para crear otro objeto el cual sí será la clase que usaré para instanciar los demás objetos, me he puesto a buscar información sobre constructores, prototipos y demás.

Al cabo de un buen rato he dado con una solución válida para mi problema, ya que yo quiero mantener ciertas variables y ciertos métodos privados; y con la información que había obtenido de mi búsqueda siempre tenía todas las variables a la disposición de la instancia que creaba.

La solución es la siguiente:

var miObjeto = function() {
    var self = this,
        _value = 0;

    // Cogemos las propiedades genéricas

    Objeto.apply(this);

    // Definimos los getters y los setters

    self.clase.__defineGetter__('value', function() {
      return _value;
    });
    self.clase.__defineSetter__('value', function(v) {
      _value = v;
      self._bind(); // Llamamos a la función de vinculación
    });

    return self.clase; // Devolvemos únicamente la clase
  }

Como los constructores en javascript son funciones y todas las funciones tienen el método call, lo que se me ha ocurrido es llamar a la función/constructor Objeto sobre miObjeto, con lo que se consigue que se definan dentro de miObjeto todas las propiedades y métodos que estaban presentes en Objeto.

Luego utilizo la otra manera de definir getters y setters, que tienen javascript, para definir las demás propiedades de miObjeto y por último devuelvo el objeto clase que contiene los métodos públicos que deseo que tenga la instancia que utilice dicha clase.

El uso de estas nuevas clases es igual que en el artículo anterior, con la diferencia de que si ahora creo, por ejemplo, un miObjeto2, no tengo que volver a implementar la funcionalidad de vincular ya que la puedo heredar de Objeto.

var miObjeto2 = function() {
    var self = this,
        _enable = 0;

    // Cogemos las propiedades genéricas

    Objeto.apply(this);

    // Definimos los getters y los setters

    self.clase.__defineGetter__('enable', function() {
      return _enable;
    });
    self.clase.__defineSetter__('enable', function(e) {
      _enable = e;
      self._bind(); // Llamamos a la función de vinculación
    });

    return self.clase; // Devolvemos únicamente la clase
  }
  var miObjetoReal = new miObjeto();
  var miObjetoReal2 = new miObjeto2();
  miObjetoReal.bind('value', miObjetoReal2, function(e) {
    (e.value != '') && (this.enable = 1) || (this.enable = 0);
  });

También a estos objetos se les podría añadir la vinculación con un elemento DOM, como en el artículo anterior, y tendríamos unos objetos con los que trabajar sin preocuparnos de las actualizaciones de la interfaz.

Referencias

http://www.webdeveloper.com/forum/showthread.php?t=243971
http://www.3site.eu/doc/
http://stackoverflow.com/questions/6039676/copying-javascript-getters-setters-to-another-prototype-object