jQuery.sub(), la segunda joya de jQuery 1.5

03 Feb 2011

En el último post revisamos una de las novedades más relevantes de la recién liberada versión 1.5 de jQuery, el objeto Deferred. En esta ocasión, vamos a tratar la otra gran novedad, el objeto jQuery.sub().

Gracias a jQuery.sub(), podemos sobreescribir o modificar los métodos nativos de jQuery en un nuevo objeto sin que estas modificaciones afecten a sus referencias originales. Esto quiere decir que podemos tener varias instancias de un objeto con comportamiento diferente manteniendo siempre el original intacto.

Esta funcionalidad, interesante pero aparentemente de poca utilidad, empieza a ganar enteros cuando pensamos en grandes arquitecturas o en librerías completas. De hecho, la flexibilidad que permite es tal, que podemos incluso modificar la propia librería jQuery en otra instancia dejando intacta la original…

jQuery.sub(), una joya de enorme potencial

Según la documentación oficial, jQuery.sub() crea una nueva copia de jQuery cuyas propiedades y métodos pueden ser modificados sin afectar el objeto jQuery original.

Su sintaxis no puede ser más simple:

jQuery.sub()

Existen dos escenarios en los que el uso de este método resulta especialmente útil:

  • Cuando necesitamos sobreescribir métodos jQuery sin destruir los originales completamente.
  • Cuando necesitamos encapsular o manejar el ámbito (namespacing) general de los plugins jQuery.

Uso básico

Para crear un objeto jQuery alternativo sobre el que realizar nuestras modificaciones, solo necesitamos declarar una variable sobre la que instanciaremos nuestro clon:

(function() {
  var subjQuery = jQuery.sub();
} )();

Eso es todo; con el código anterior hemos creado una función autoejecutable que envía una copia de jQuery a nuestra nueva variable subjQuery al ámbito (namespacing) global.

NOTA: Para conocer más acerca del Namespacing en Javascipt, el siguiente artículo publicado en Ontuts puede resultar una lectura interesante: Namespacing en Javascript.

Añadiendo un nuevo método jQuery

Con el siguiente ejemplo, añadimos un nuevo método a nuestro clon jQuery que no será accesible desde el original.

(function() {
  var myjQuery = jQuery.sub();
  myjQuery.fn.myCustomMethod = function(){
    console.log( 'My custom method' );
  };
  myjQuery( document ).ready( function() {
    myjQuery( 'body' ).myCustomMethod();  // My custom method
  } );
} )();
 
console.log( typeof jQuery( 'body' ).myCustomMethod ); // Undefined

De este modo, hemos introducido una nueva funcionalidad sólo accesible desde nuestro clon jQuery. La librería original no tiene acceso al nuevo método.

Modificando métodos preexistentes

En lugar de añadir algo nuevo, podemos sobreescribir los métodos nativos sin alterar de una forma definitiva los originales.

El siguiente código ha sido extraído de la documentación jQuery por resultar especialmente interesante; traduzco los comentarios para una mayor claridad:

(function() {
  var myjQuery = jQuery.sub();
  myjQuery.fn.remove = function() {
    // Nueva funcionalidad: Cada vez que eliminemos un objeto jQuery,
    // lanzaremos el evento 'my_remove'.
    this.trigger( "my_remove" );
    // Nos aseguramos de llamar al método original jQuery 'remove'
    // para que, además de lanzar el evento anterior, continuemos
    // con el comportamiento original
    return jQuery.fn.remove.apply( this, arguments );
  };
 
  myjQuery( function( $ ) {
    $(".menu").click(function() {
      // Llamamos al 'remove' de nuestro jQuery modificado
      $(this).find(".submenu").remove();
    } );
 
    // Al llamar al nuevo 'remove', lanzamos el evento 'my_remove' que
    // tenemos que definir
    $( document ).bind( "my_remove", function( e ) {
      // Nuestro evento realiza la acción deseada, en este caso,
      // esconder el padre del elemento que ha disparado el evento
      $( e.target ).parent().hide();
    } );
  } );
 
} )();
 
// El objeto original jQuery no lanzará el evento 'my_remove'.
// Esta funcionalidad solo pertenece a nuestro jQuery modificado 'myjQuery'.

Con esto ejemplo, contamos con dos comportamientos para un mismo método el cual depende del objeto desde el que se invoque. En definitiva, además de sobreescribir un método, conservamos el original para futuras referencias.

Usando jQuery.sub() en los plugins jQuery

Mediante jQuery.sub(), podemos crear nuevos plugins jQuery que añadan funcionalidades a la librería oficial sin alterar el contexto global. Conseguimos con esto una mayor integración de los elementos garantizándonos que siempre que se invoquen estarán disponibles.

(function() {
  // Create a new copy of jQuery using sub()
  var plugin = jQuery.sub();
  // Extend that copy with the new plugin methods
  plugin.fn.extend( {
    toRed: function() {
      return this.css("background-color","red");
    },
    toBlue: function() {
      return this.css("background-color","blue");
    }
  });
  // Add our plugin to the original jQuery
  jQuery.fn.myplugin = function() {
    this.addClass("plugin");
    // Make sure our plugin returns our special plugin version of jQuery
    return plugin( this );
  };
} )();
 
$(document).ready(function() {
  // Call the plugin, open method now exists
  $('#box').myplugin().toBlue();
  // Note: Calling just $("#box").toBlue() won't work!
} );

Nuestro plugin (extremadamente básico) ofrece dos nuevos métodos que pueden aplicarse a los objetos jQuery seleccionados: toRed y toBlue. Mediante jQuery.sub(), añadimos ambas funcionalidades a la librería original permitiendo su uso inmediatamente.

Conclusión

Con el nuevo método jQuery.sub(), jQuery aproxima Javascript a un lenguaje orientado a objetos más ‘tradicional’. Nos permite instanciar a la propia librería para añadir nuevos métodos o sobreescribir aquellos preexistentes preservando el comportamiento nativo.

Además de esto, la elaboración de plugins jQuery da un paso en cuanto a su integración con el núcleo de la librería permitiendo una disponiblidad inmediata además de una arquitectura más clara y legible.

Tal y como avanzamos en el post anterior, jQuery continúa dando pasos de gigante para ofrecerse como una opción válida cara a grandes proyectos de arquitecturas complejas.

Más:

Aún no tenemos debug!
Ningún marciano se ha comunicado.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *