JavaScript limpio


No soy quién para escribir un post sobre JavaScript, y menos sobre buenas prácticas. Sin embargo, el otro día mi colega @pladaria, que sí que es un crac de JavaScript, me dio un curso intensivo de 10 minutos... y le pedí permiso para transcribirlo en mi blog.

Me gustó todo lo que dijo, así que trataré de ser fiel.

Creación de objetos

Hay muchas cosas a evitar en JavaScript: new y this son las principales (al menos para cosas que hagas tú). Pero... ¿Cómo se crean objetos entonces? Pues fácil: creando fábricas de objetos.

Veamos un ejemplo. Vamos a guardar usuarios, por lo que necesitamos una fábrica de usuarios:

var UserFactory = function(name, age) {
    var privateAge = age;

    var exports = {};
    exports.name = name;
    exports.getAge = function () { return privateAge };
    return exports;
}

En este caso tenemos un atributo público (name) y un método público (getAge) que accede a una variable privada (age).

La manera de crear objetos es sencilla: Basta con invocar el constructor, es decir, la fábrica:

var user = UserFactory('Fulanito', 20);

Constructores

En ocasiones no hay más remedio que utilizar constructores. En ese caso se puede hacer algo así:

var Constructor = function(param1, param2) {
    if (this instanceOf Constructor) {
        this.param1 = param1;
        this.param2 = param2;
        return this;
    }
    return new Constructor(param2, param2);
}

Y así se pueden crear instancias con o sin new. De esta forma se evita utilizar this con algo distinto del objeto creado, ya que si en algún momento se crea un objeto sin new, el this del contexto podría ser window u otra cosa, y JavaScript no avisará.

Herencia

Si ya no tenemos objetos propiamente dichos y creados con new... ¿Cómo establecemos la herencia?

Pues resulta bastante sencillo, ya que basta crear un objeto "padre" y añadirle los métodos/atributos deseados:

var FlyingUserFactory = function(name, age, speed) {
    var privateSpeed = speed;

    user = UserFactory(name, age);
    user.getSpeed = function() { return privateSpeed };
    return user;
}

Este método tiene la ventaja adicional de que no tiene que exportar la prototype-chain, por lo que es hasta más eficiente.

Módulos

Ya tenemos objetos, pero... se puede llegar más lejos. Veamos un módulo que permite la gestión de listas (un poco absurdo, pero interesante como ejemplo):

var module = (function(clone) {
  var items = [];

  var exports = {};
  exports.add = function(item){
    items.push(clone(item));
  }

  return exports;
})(Y.clone); // usando el framework Yui; _.clone si preferimos underscore

Lo primero que salta a la vista es que el módulo es el resultado de invocar a una función. Ésta requiere el argumento clone. Sí, es una inyección de dependencias. De esta manera resulta muy sencillo probar el módulo, saber qué dependencias tiene el módulo y es fácil cambiar de framework. En el ejemplo estamos usando YUI, pero utilizar Underscore es tan simple como cambiar la llamada. Sería igual de sencillo usar JQuery.

La variable items se declaró dentro del módulo, por lo que es privada.

En la variable exports se van añadiendo las variables y métodos exportados, que son los que definen el módulo. En este caso, se define la función add que permite insertar un elemento.

Conclusión

El resultado es un código JavaScript limpio, sencillo, modular y fácil de probar. Todo lo contrario a cualquier código JavaScript que yo haya escrito hasta ahora. Y en sólo 10 minutos.

Gracias de nuevo a @pladaria, ya que no sólo ha sido el inspirador de este post, sino también su corrector y casi redactor.


Comentarios

Comments powered by Disqus