Clases avanzadas en JS

En el artículo anterior escribí una manera simple de tener clases en JS sin tener que usar ES6 aunque demasiado simples si queremos hacer uso de metodologías avanzadas de OOP.

Para paliar la deficiencia de OOP en Javascript, durante muchos años usé un framework llamado Qooxdoo el cual aporta todo un sistema de clases bastante avanzados que me simplificó la vida en proyectos bastante grandes de Javascript pero hoy en día encontré una alternativa más liviana aunque no aporta la misma funcionalidad.

Tengo que reconocer que no soy fan de EmberJS (aunque he tenido que ser arquitecto de aplicaciones complejas con este framework) pero también tengo que reconocer que su sistema de clases aporta cosas interesantes: herencia, mixins, bindings, observadores, propiedades calculadas, etc.

El sistema de clases ofrecido por EmberJS amplía el que vimos en el artículo anterior (si bien usan el paqute core-object como base) y su principal clase se llama Ember.Object. A partir de esta clase extienden todos los objetos.

Instalación

Al ser un paquete de NodeJS, se puede instalar de manera simple con ejecutar:

  1. $ npm install ember-metal ember-runtime

Uso

A continuación pondré un fragmento de código donde puede verse cómo usar el sistema de clases:

  1. require('ember-metal');
  2. require('ember-runtime');
  3.  
  4. var jf = {};
  5.  
  6. jf.Mixin = Ember.Mixin.create(
  7.     {
  8.         init: function ()
  9.         {
  10.             this._super();
  11.             console.log('jf.Mixin::init');
  12.         }
  13.     }
  14. );
  15.  
  16. jf.Base = Ember.Object.extend(
  17.     jf.Mixin,
  18.     {
  19.         info         : '',
  20.         infoObserver : Ember.observer(
  21.             function ()
  22.             {
  23.                 console.log('jf.Base::infoObserver: %s', this.info);
  24.             },
  25.             'info'
  26.         ),
  27.         destroy      : function ()
  28.         {
  29.             console.log('jf.Base::destroy');
  30.             this._super();
  31.         },
  32.         init         : function ()
  33.         {
  34.             this._super();
  35.             console.log('jf.Base::init -- info: %s', this.info);
  36.         }
  37.     }
  38. );
  39.  
  40. jf.Child = jf.Base.extend(
  41.     {
  42.         destroy: function ()
  43.         {
  44.             console.log('jf.Child::destroy');
  45.             this._super();
  46.         },
  47.         init: function ()
  48.         {
  49.             this._super();
  50.             console.log('jf.Child::init');
  51.         }
  52.     }
  53. );
  54.  
  55. var child = jf.Child.create(
  56.     {
  57.         info : 'Learning Ember.Object'
  58.     }
  59. );
  60. child.set('info', 'Test observer');
  61. child.destroy();

La salida del código anterior sería la siguiente:

  1. jf.Mixin::init
  2. jf.Base::init -- info: Learning Ember.Object
  3. jf.Child::init
  4. jf.Base::infoObserver: Test observer
  5. jf.Child::destroy
  6. jf.Base::destroy

Para que funcionen los observadores es necesario hacer uso del método set.